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_NAME1 - 将
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: