CTF-safu-wallet
CTF-safu-wallet
题目源码点击。
题目要求:这是一个多签名钱包,已经有一位顾客存入钱,然后你要将它的钱永远困住在这个钱包里
首先看到合约代码:很清晰的辨别了,SafuWallet合约是代理合约,SafuWalletLibrary合约是逻辑合约,这样分开,就好理解了
对于多签名钱包,我的理解就是,不止一个管理员,至少要俩个管理员就可以管理这个钱包了。
逻辑合约里有kill函数,如果能调用,这应该是最便捷的解题方式了
function kill(address _to) onlymanyowners(sha3(msg.data)) external { |
很遗憾的是,有个onlymanyowners
限制,这也就是多签名钱包的魅力了吧。
看到代理合约中,构造函数还是有点东西。
constructor(address[] memory _owners, uint _required, uint _daylimit) { |
又是熟悉的delegatecall
,代理合约委托调用了逻辑合约里的initWallet函数,执行环境是在代理合约,改变的状态变量也是在代理合约中,也就是说在代理合约中,这个所有者是可以改变的,如果只有我们自己,那么就可以成为多签名钱包的唯一所有者,然后再调用逻辑合约里的kill函数,传入代理合约的地址,销毁它,这样就不需要其他人的所有者的同意,就可以销毁,那位存钱的人,想要取钱,是不行的。
还有一种情况就是把所有者列表都设置为空,然后再调用kill函数时就没有任何所有者确认了。
攻击思路:
改变所有者的列表,将他们设置为空。调用safuWalletLibrary.initWallet(addresses(0), 1, type(uint).max)
,设置要求,只需要一个确认就可以执行操作。最后调用kill函数,即可。
个人认为:就是逻辑合约里的kill函数没有任何限制,只要所有者列表为空,或者攻击者成为了所有者,都可以调用。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.