PHP代码审计系列基础文章(四)之代码执行漏洞篇
字数 1296 2025-08-11 21:26:21
PHP代码审计:代码执行漏洞详解
1. 代码执行漏洞原理
代码执行漏洞是指攻击者能够通过应用程序的输入点注入恶意代码,并在服务器端执行。PHP中由于提供了多种灵活的函数来执行动态代码,当这些函数的参数可控时,就可能造成严重的安全问题。
核心风险点:
- 通过代码执行函数可以直接调用PHP任意代码
- 代码执行可以进一步调用命令执行函数来控制系统
- 导致RCE(远程代码/命令执行)漏洞
2. 主要代码执行函数及利用方式
2.1 eval()函数
功能:将字符串作为PHP代码执行
危险示例:
$arg = $_REQUEST['value'];
eval($arg);
利用方式:
- 传入
phpinfo();可查看PHP配置信息 - 必须用分号结尾,否则会报错
- 可执行多条语句,用分号分隔
2.2 assert()函数
功能:检查断言是否为false,但也可执行代码
危险示例:
$arg = $_REQUEST['value'];
assert($arg);
特点:
- 比eval()更灵活,不需要分号结尾
- 可拆分调用绕过WAF:
$a='ass'; $b='ert'; $c=$a.$b;
@$c($_REQUEST['value']);
2.3 preg_replace()函数
危险模式:使用/e修正符时
危险示例:
@preg_replace("/123/e",$_REQUEST['value'],"1234567");
原理:
/e模式使替换值被当作PHP代码执行- 在字符串"1234567"中匹配"123"并用传入值替换
2.4 create_function()函数
功能:创建匿名函数
危险示例:
$a = create_function('$arg',$_REQUEST['x']);
利用方式:
- 第二个参数会在内部执行eval()
- 需要闭合匿名函数的
}使代码独立执行
2.5 array_map()函数
功能:将回调函数作用到数组的每个元素
危险示例:
array_map($_REQUEST['arg1'],array($_REQUEST['arg2']));
原理:
- 第一个参数作为回调函数执行
- 相当于
assert(phpinfo())形式
2.6 call_user_func()系列
call_user_func():
call_user_func($_GET['a1'],$_GET['a2']);
call_user_func_array():
call_user_func_array($_GET['arg1'],$_GET['arg2']);
// arg2需为数组形式
2.7 array_filter()函数
危险示例:
array_filter(array($_REQUEST['arg1']),$_REQUEST['arg2']);
特点:
- 第一个参数是回调函数的参数
- 第二个参数是回调函数
2.8 ob_start()函数
危险示例:
$cmd = 'system';
ob_start($cmd);
echo "$_REQUEST['arg']";
ob_end_flush();
2.9 usort()函数
危险示例(PHP>=5.6):
usort($_REQUEST,"assert");
功能:使用自定义函数对数组排序
2.10 array_walk()函数
危险示例:
array_walk($_GET['arg1'],$_GET['arg2']);
注意:传入参数为数组,形参需加[]
2.11 动态函数
危险示例:
$_REQUEST['arg1']($_REQUEST['arg2']);
原理:直接拼接字符串作为函数名调用
3. 代码审计要点
- 识别危险函数:熟悉上述所有可能执行代码的函数
- 参数追踪:检查这些函数的参数是否用户可控
- 输入过滤:查看是否有对用户输入进行有效过滤
- 上下文分析:分析代码执行的环境和条件
- 利用链构造:考虑如何闭合语句或构造有效payload
4. 防御建议
- 避免直接使用eval()等危险函数
- 使用白名单限制可执行函数
- 对用户输入进行严格过滤和转义
- 禁用危险函数(如eval、assert等)
- 使用安全的替代方案实现相同功能
5. 总结
代码执行漏洞是PHP应用中最危险的漏洞之一,审计时需要特别关注文中提到的各类函数。掌握这些函数的特性和利用方式,有助于在代码审计中快速发现潜在风险点。实际审计中应结合具体业务场景,分析参数传递路径,判断是否存在可利用的代码执行点。