Ethernaut Challenge
Learn how to stop common hacks.
Attacking a Contract
- Copy contract in Remix
- Create contractAttack.sol file
- Import Contract to attack
- Create reference to contract in the constructor
// TargetContractAttack.sol
import './TargetContract.sol';
contract TargetContractAttack {
TargetContract target;
constructor(address _targetAddr) public {
// DON'T USE NEW !!!
// When you don't use new you get a reference to an existing contract
target = TargetContract(_target);
}
// Attack logic
}
General strategy:
- Claim ownership of the contract
- Extract the balance
Or aim to be a nuisance and make the contract inoperable.
Challenges
Challenge | Vulnerability | Best Practice | Use Attack Contract |
---|---|---|---|
Fallback | Fallback Function | ||
Fallout | Mistyped Constructor Function | Use Constructor | |
Coin Flip | Use an Oracle for Randomness | true | |
Telephone | |||
Token | |||
Delegation | DelegateCall | Consider impact on State | |
Force | selfdestruct | Be aware | true |
Vault | Can decrypt Passwords | Store passwords off-chain | |
King | Transfer to malicious contracts | Handle transfer failures | true |
Re-entrancy | Failing Loop Logic | Update Balances before Transfer | true |
Elevator | Understand Interfaces | true | |
Privacy | Understand Slot Storage | true | |
Gatekeeper One | TODO: | ||
Gatekeeper Two | Contract Initialisation & Bitwise comparison | true | |
Naught Coin | Approve Pattern | ||
Preservation | DelegateCall | ||
Recovery | |||
Magic Number | |||
Alien Codex | |||
Denial | |||
Shop | |||
Dex | |||
Dex Two | |||
Puzzle Wallet | |||
Motorbike |
Fallback
The default (fallback) function called if a contract is called without a function name or an incorrect function name is provided.
As a best practice this technique should be avoided in favour of providing a recieve function.
Solutiion
Send an amount of Eth into an unnamed transaction that passes a requirement to transfer owner to the calling address.
Then call withdraw.
contract.sendTransaction({value, 1});
Fallout
There was typo in creating the constructor name creating a public function by accident.
Best Practice use constructor as the contructor name not the name of the contract.
Coin Flip
Reviews randomness by trying to use blockhash
The problem is that anyone can investigate this number, as this is information of historical record.
With the blockhash info a hacker can decrypt codes that allow them to cheat logic.
Best practice: use audited data oracles.
Solution
Create a proxy contract in Remix to replicate the function logic and find the correct inputs to send into the original contract to win the game.
Delegation
Delegate call gives trust to another contract to change the state of the contract you are calling from.
Need to get sha3 of the function. Used web3.utils.sha3("pwn()")
To execute call with transaction when no method name specified.
Questions:
- What is ethers equivalent of web3.utils?