[红日安全]代码审计Day5 - escapeshellarg与escapeshellcmd使用不当
字数 1538 2025-08-29 08:32:25

PHP escapeshellarg与escapeshellcmd使用不当漏洞分析

1. 漏洞背景

本文分析PHP中escapeshellarg()escapeshellcmd()函数同时使用时可能导致的命令注入漏洞,以及相关的邮件函数安全问题。

2. 核心漏洞原理

2.1 mail函数的安全问题

PHP的mail()函数底层调用Linux的sendmail程序发送邮件,其第五个参数additional_parameters可以传递sendmail支持的选项:

  • -O option=value - 设置队列目录
  • -X logfile - 指定日志文件
  • -f from_email - 指定发件人邮箱

其中-X参数可以指定日志文件路径,如果将日志写入web目录并设置为.php后缀,可能导致代码执行。

2.2 filter_var()的绕过

filter_var($email, FILTER_VALIDATE_EMAIL)用于验证邮箱格式,但存在以下问题:

  1. 特殊字符必须放在双引号中
  2. 可以通过转义空格绕过检测
  3. 通过重叠单引号和双引号欺骗验证

2.3 escapeshellcmd与escapeshellarg的交互问题

当这两个函数一起使用时,可能导致特殊字符逃逸:

  1. escapeshellarg先对单引号转义并添加外层引号
  2. escapeshellcmd再对特殊字符转义
  3. 转义字符被解释导致引号逃逸

示例分析

$input = "127.0.0.1' -v -d a=1";
$arg = escapeshellarg($input); // 结果为:'127.0.0.1'\'' -v -d a=1'
$cmd = escapeshellcmd($arg);   // 结果为:'127.0.0.1'\\'' -v -d a=1\'

最终执行的命令相当于:

curl 127.0.0.1\ -v -d a=1'

3. PHPMailer实例分析

3.1 CVE-2016-10033

漏洞原因

  1. 未对$params变量严格过滤
  2. safe_mode关闭时,mail()函数传入$params参数
  3. $params来自$this->Sender,而setFrom函数中的邮箱验证可绕过

利用Payload

a( -OQueueDirectory=/tmp -X/var/www/html/x.php )@a.com

3.2 CVE-2016-10045

修复后绕过
添加了escapeshellcmd函数,但结合mail()底层的escapeshellarg,导致单引号逃逸。

利用Payload

a'( -OQueueDirectory=/tmp -X/var/www/html/x.php )@a.com

最终执行的参数变为:

'-fa'OQueueDirectory=/tmp -X/var/www/html/test.php \)@a.com\'

3.3 漏洞利用条件

  1. PHP版本 < 5.2.0
  2. PHPMailer < 5.2.18 (CVE-2016-10033) 或 < 5.2.20 (CVE-2016-10045)
  3. PHP未安装PCRE扩展
  4. safe_mode = false

4. 修复建议

  1. 避免同时使用escapeshellcmd()escapeshellarg()函数
  2. 对用户输入进行严格验证
  3. PHPMailer官方修复方案:检测转义字符时不传递-f参数

5. CTF题目分析

题目代码关键点:

  1. 使用parse_url检查URL scheme必须是http或https
  2. 对URL参数先后应用escapeshellargescapeshellcmd
  3. 通过system("curl " . $url)执行命令

利用思路
利用escapeshellargescapeshellcmd的交互问题构造特殊URL,绕过scheme检查并执行命令。

6. 总结

  1. PHP邮件函数底层实现存在安全隐患
  2. 邮箱验证函数可被绕过
  3. shell转义函数组合使用可能导致参数逃逸
  4. 实际案例(PHPMailer)展示了漏洞的严重性
  5. 修复时需要全面考虑函数交互影响

7. 防御措施

  1. 使用最新版本的PHP和库文件
  2. 对用户输入实施严格的白名单验证
  3. 避免不必要的shell命令执行
  4. 如必须使用shell命令,选择安全的参数传递方式
  5. 定期进行安全审计,特别是对敏感函数的使用
PHP escapeshellarg与escapeshellcmd使用不当漏洞分析 1. 漏洞背景 本文分析PHP中 escapeshellarg() 与 escapeshellcmd() 函数同时使用时可能导致的命令注入漏洞,以及相关的邮件函数安全问题。 2. 核心漏洞原理 2.1 mail函数的安全问题 PHP的 mail() 函数底层调用Linux的sendmail程序发送邮件,其第五个参数 additional_parameters 可以传递sendmail支持的选项: -O option=value - 设置队列目录 -X logfile - 指定日志文件 -f from_email - 指定发件人邮箱 其中 -X 参数可以指定日志文件路径,如果将日志写入web目录并设置为.php后缀,可能导致代码执行。 2.2 filter_ var()的绕过 filter_var($email, FILTER_VALIDATE_EMAIL) 用于验证邮箱格式,但存在以下问题: 特殊字符必须放在双引号中 可以通过转义空格绕过检测 通过重叠单引号和双引号欺骗验证 2.3 escapeshellcmd与escapeshellarg的交互问题 当这两个函数一起使用时,可能导致特殊字符逃逸: escapeshellarg 先对单引号转义并添加外层引号 escapeshellcmd 再对特殊字符转义 转义字符被解释导致引号逃逸 示例分析 : 最终执行的命令相当于: 3. PHPMailer实例分析 3.1 CVE-2016-10033 漏洞原因 : 未对 $params 变量严格过滤 当 safe_mode 关闭时, mail() 函数传入 $params 参数 $params 来自 $this->Sender ,而 setFrom 函数中的邮箱验证可绕过 利用Payload : 3.2 CVE-2016-10045 修复后绕过 : 添加了 escapeshellcmd 函数,但结合 mail() 底层的 escapeshellarg ,导致单引号逃逸。 利用Payload : 最终执行的参数变为: 3.3 漏洞利用条件 PHP版本 < 5.2.0 PHPMailer < 5.2.18 (CVE-2016-10033) 或 < 5.2.20 (CVE-2016-10045) PHP未安装PCRE扩展 safe_ mode = false 4. 修复建议 避免同时使用 escapeshellcmd() 和 escapeshellarg() 函数 对用户输入进行严格验证 PHPMailer官方修复方案:检测转义字符时不传递 -f 参数 5. CTF题目分析 题目代码关键点: 使用 parse_url 检查URL scheme必须是http或https 对URL参数先后应用 escapeshellarg 和 escapeshellcmd 通过 system("curl " . $url) 执行命令 利用思路 : 利用 escapeshellarg 和 escapeshellcmd 的交互问题构造特殊URL,绕过scheme检查并执行命令。 6. 总结 PHP邮件函数底层实现存在安全隐患 邮箱验证函数可被绕过 shell转义函数组合使用可能导致参数逃逸 实际案例(PHPMailer)展示了漏洞的严重性 修复时需要全面考虑函数交互影响 7. 防御措施 使用最新版本的PHP和库文件 对用户输入实施严格的白名单验证 避免不必要的shell命令执行 如必须使用shell命令,选择安全的参数传递方式 定期进行安全审计,特别是对敏感函数的使用