【八个月网安课程】第十二周·周五:命令/代码执行点审计——eval、assert、system 参数追踪
今天将直面 PHP 中最危险的漏洞类型——命令注入与代码执行。通过审计eval、assert、system等函数的调用追踪其参数来源将能够识别出留存在代码中的致命后门或业务逻辑漏洞。掌握这些审计技能意味着能从源码层面预见攻击者可能造成的最大破坏。第十二周·周五命令/代码执行点审计——eval、assert、system 参数追踪 今日学习目标达成效果能区分代码执行漏洞与命令执行漏洞前者在 PHP 上下文执行任意代码eval、assert后者执行操作系统命令system、exec能列出PHP 中所有可能导致代码/命令执行的危险函数eval()、assert()、preg_replace()配合/e修饰符、create_function()、call_user_func()、system()、exec()、shell_exec()、passthru()、反引号能审计危险函数的参数是否来自用户可控的输入源并判断其过滤是否可被绕过能在 DVWA 或自建靶场源码中定位到命令执行漏洞如 Command Injection 源码并追踪变量流能独立完成一个包含动态函数调用的代码执行漏洞利用并写出 POC能总结防御命令/代码执行漏洞的铁律永远不要将用户输入直接或间接传入执行函数使用硬编码或白名单限制命令与参数。 一、代码执行与命令执行的本质区别类型执行环境典型函数危害代码执行PHP 解释器eval(),assert(),preg_replace()with/e执行任意 PHP 代码可获取数据库凭证、读写文件、创建后门命令执行操作系统 Shellsystem(),exec(),shell_exec(),passthru()执行任意系统命令直接控制服务器共同点两者均是将用户数据作为“指令”传递给了执行引擎根源在于数据与代码的边界被打破。 二、危险函数详解及审计模式1.eval()—— 最臭名昭著的代码执行eval($code);审计关键$code中是否包含外部变量即使是部分拼接只要包含用户输入就可能被注入。危险模式eval(echo $user;);如果$user来自$_GET可注入; system(id);//。搜索eval\s*\(2.assert()—— 调试函数变成后门assert($assertion);在 PHP 5.x 中assert()会将字符串参数作为 PHP 代码执行。如果$assertion为字符串且可控危害等同eval()。PHP 7 中默认禁用字符串执行但审计老旧代码时仍需留意。3.preg_replace()/e修饰符preg_replace(/pattern/e,$replacement,$subject);/e修饰符会将$replacement作为 PHP 代码执行$subject中的捕获组会被插入。已从 PHP 5.5 起废弃PHP 7 移除。但审计遗留系统时极重要。搜索preg_replace\s*\(.*\/e4.create_function()—— 匿名函数陷阱$funccreate_function($a,return $a * .$_GET[multiplier].;);内部使用eval()创建函数参数直接拼接PHP 7.2 起废弃旧系统常见。5. 动态函数调用call_user_func()/$func()$action$_GET[action];call_user_func($action);或$action();如果攻击者传入system再控制参数即可执行系统命令。6. 命令执行函数system($cmd)执行命令并直接输出。exec($cmd, $output)执行命令输出存入数组。shell_exec($cmd)通过 Shell 执行返回全部输出。passthru($cmd)执行并直接输出原始结果。反引号$cmd等价于shell_exec。审计关键$cmd是否包含用户输入是否允许任意命令或参数 三、参数追踪实战从输入到毁灭审计命令/代码执行的标准路径定位危险函数Sink。追溯第一个参数是否包含外部变量。检查过滤是否使用了escapeshellcmd()或escapeshellarg()但两者也无法完全防御如果参数拼接在命令字符串中而非单独传递。研判能否构造 payload 突破限制。示例$ip$_POST[ip];system(ping -c 4$ip);$ip可控直接进入system无过滤。攻击者输入127.0.0.1; cat /etc/passwd实现命令注入。即使使用escapeshellcmd($ip)它不阻止;等分隔符。若用escapeshellarg会将整个值作为单个参数但开发常误用。安全替代使用proc_open或直接调用不带 shell 的 API。✍️ 四、动手实践审计命令/代码执行漏洞实践 1审计 DVWA Command Injection 源码打开dvwa/vulnerabilities/exec/source/low.php$target$_REQUEST[ip];if(stristr(php_uname(s),Windows NT)){$cmdshell_exec(ping .$target);}else{$cmdshell_exec(ping -c 4 .$target);}echopre$cmd/pre;审计分析输入源$_REQUEST[ip]无任何过滤。危险函数shell_exec拼接命令。漏洞典型命令注入可执行任意系统命令。利用127.0.0.1; whoami。Medium 级别$target$_REQUEST[ip];$substitutionsarray(,;);$targetstr_replace(array_keys($substitutions),$substitutions,$target);$cmdshell_exec(ping -c 4 .$target);过滤了和;但未过滤、|等。仍可绕过127.0.0.1 whoami。审计结论黑名单过滤不充分。High 级别增强了黑名单但可能依然可通过|或%0a绕过。源码处仍依赖危险函数最安全的是根本不使用shell_exec。实践 2审计动态函数调用漏洞创建dispatch.php$action$_GET[action]??index;$param$_GET[param]??;if(function_exists($action)){$action($param);}攻击?actionsystemparamid执行系统命令。防御使用白名单映射如$actions [index doIndex, login doLogin];并仅允许列表中的函数。实践 3使用 Seay 审计一个 CMS 中的eval调用在 Seay 中打开一个老旧 CMS如织梦早期版本或简单 PHP CMS。搜索eval逐条分析是否有用户输入拼接常见于模板解析、插件系统。如发现eval(? . file_get_contents($tpl));若$tpl可控可通过文件写入 eval 组合攻击。记录将发现点整理到审计笔记注明文件路径、行号、变量来源。 五、课后测试题与解析测试题 1请写出至少 5 个 PHP 中可能导致代码执行或命令执行的函数。参考答案eval()直接执行 PHP 代码。assert()在 PHP 5.x 下可执行传入的字符串。preg_replace()with/e执行替换字符串中的 PHP 代码。system()执行系统命令并输出结果。exec()、shell_exec()、passthru()执行系统命令。create_function()内部使用eval创建函数。call_user_func()配合可控函数名动态调用任意函数。测试题 2审计以下代码判断是否存在漏洞并说明原因。$cmd$_GET[cmd];$safe_cmdescapeshellcmd($cmd);system(ls -l .$safe_cmd);参考答案仍然存在命令注入漏洞。escapeshellcmd()会对整个命令字符串进行转义防止多命令执行如;被转义但它不会阻止参数注入。攻击者可以输入. ; rm -rf *其中;会被转义但更隐蔽的是输入-al /etc | cat或者利用ls的参数来读取敏感目录。因为$safe_cmd直接被附加为ls的参数攻击者可控制参数内容造成信息泄露或文件操作。正确做法是避免直接拼接命令或使用escapeshellarg()并结合严格的参数白名单验证。✅ 今日学习效果自检清单我能区分代码执行与命令执行并列举各自的危险函数我在 DVWA 的 Command Injection 源码中追踪了从输入到shell_exec的完整路径我理解eval、assert、preg_replace的风险并能在代码中识别它们我使用 Seay 搜索了目标源码中的eval和system并人工研判了数个实例我掌握了防御此类漏洞的核心原则避免使用动态执行函数使用白名单与参数化我知道escapeshellcmd与escapeshellarg的区别及各自局限性⚠️ 阶段避坑重点不要迷信escapeshellcmd它不能阻止参数注入如果用户输入作为命令的参数仍可能产生危害。注意 PHP 版本差异assert()在 PHP 7 中不再将字符串作为代码执行但旧代码遗留仍构成风险。preg_replace的/e已在 PHP 7 中移除但老系统可能仍在使用。变量函数调用极具迷惑性$var()或call_user_func($var)容易被审计者忽略。务必检查所有动态调用点。命令执行不一定需要直接回显结合盲注技巧如 DNS 外带、延时攻击者仍可窃取数据。审计时不能因为“无回显”就判定低危。框架中的危险调用现代框架虽然封装但若提供Process组件或允许直接执行命令仍需追踪用户输入是否污染参数。今天你掌握了 PHP 中最具破坏性漏洞的审计方法。明天我们将结合本周所学进行代码审计的综合实战对一个完整的 PHP 靶场如 bWAPP进行系统审计撰写漏洞报告练习从黑盒到白盒的完整漏洞发现流程。请保留今天的所有审计笔记明天将需要它们来对比和扩展。