escapeshellarg与escapeshellcmd造成的逃逸
escapeshellcmd()
escapeshellcmd()功能escapeshellcmd:
escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。
反斜线(\)会在以下字符之前插入: *&#;`|*?~<>^()[]{}$*, \x0A 和 \xFF。 ’ 和 " 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。
**escapeshellcmd()**函数在底层代码如下(详细点 这里 https://github.com/php/php-src/blob/PHP-5.6.29/ext/standard/mail.c):
escapeshellarg()
escapeshellarg()定义
escapeshellarg— 把字符串转码为可以在 shell 命令里使用的参数
功能:escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,shell 函数包含 exec(),system() 执行运算符(反引号)
定义:string escapeshellarg ( string $arg )
具体功能作用,可以参考如下案例:
函数使用不当造成的逃逸
首先简单点来说就是一个函数把危险字符给转义了,但是这个函数用的转义危险字符的字符也是危险的,所以再到另一个函数里又把这个危险字符转义了,这导致了
**escapeshellcmd()**和 escapeshellarg一起使用,会造成特殊字符逃逸,下面我们给个简单例子理解一下:
详细分析一下这个过程:
- 传入的参数是127.0.0.1’ -v -d a=1
- 由于escapeshellarg先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。所以处理之后的效果如下:‘127.0.0.1’ ’ ’ -v -d a=1’
- 接着 escapeshellcmd 函数对第二步处理后字符串中的 以及 a=1’ 中的单引号进行转义处理,结果如下所示:‘127.0.0.1’‘’ -v -d a=1’
- 由于第三步处理之后的payload中的
\
被解释成了\\
而不再是转义字符,所以单引号配对连接之后将payload分割为三个部分,具体如下所示:
所以这个payload可以简化为 curl 127.0.0.1 -v -d a=1’ ,即向 127.0.0.1 发起请求,POST 数据为 a=1’ 。
总结一下,这题实际上是考察绕过 **filter_var()**函数的邮件名检测,通过 mail函数底层实现中调用的 **escapeshellcmd()**函数处理字符串,再结合 **escapeshellarg()**函数,最终实现参数逃逸,导致 远程代码执行。