2023 | TetCTF | WEB
TetCTFToken
题目¶
- So, this year, we have something cool for you. We hope you will enjoy it. Happy New Year. ~Cheers,
- Server: http://172.105.114.30:31337
解题思路¶
- 不太常见的 Web2 + Web3 组合题,不过幸好两个部分可以独立解题 (=ω=)
- Strellic 完成了 Web2 的部分,关键点在
app.py
中函数userType
使用了url_for('gen_token', Type=_secret_token, _external=True)
来获取_secret_reset_passwd_URL
,并向其发送包含新密码的请求- 因为
external=True
,所以会结合设置的SERVER_NAME
来生成完整的 URL - 而服务器并没有设置
SERVER_NAME
,因此会从请求头中获取Host
字段作为SERVER_NAME
1 - 将
Host
设置为可控地址,再发送重置密码的请求,就可以监听到服务器请求/secret-token/<Type>
,其中,Type
对应新的账户密码
- 因为
-
TetCTFToken/templates/dashboard.html
中给出了合约 TetCTFToken 和 FlagStore 的地址,并在 BscScan 上提供了合约的源码 -
FlagStore
是主要交互合约,可以通过函数deposit
用 BNB 换取等量的TetCTFToken
,随后可通过withdraw
将账户中所有的TetCTFToken
换回等量的 BNB - 函数
deposit
和withdraw
均使用了nonReentrant
修饰符,以防止重入攻击,即便如此,由于不符合 Checks-Effects-Interactions 模式,msg.sender.call{value: token.balanceOf(msg.sender)}("")
也是值得重点关注的对象。不能重复调用deposit
和withdraw
,那么在合约的回调函数中还能做什么呢? -
注意到
msg.sender.call
和token.burn
都使用了token.balanceOf
来获取调用者持有TetCTFToken
的数量,因此即使在msg.sender.call
触发的回调函数中转移TetCTFToken
,token.burn
也不会抛出异常 -
获取足够的
TetCTFToken
后,调用buyFlag
并传入在网站注册的用户名,最后 Buy Flag 就可以啦 :D
最后更新:
2023年1月5日 21:45:35
Contributors: