Not only good guys are excited about blockchain and crypto technologies. Bad guys are drawn by abundance of money in rotation as well.
Black hats try to employ their reverse engineering and research skills to find vulnerable smart contracts. Comparing to breaches found in regular software, vulnerabilities in smart contracts are more devastating and can yield immediate profit to attackers. $30M stolen from Parity MultiSig wallet and another $300M frozen by second attack are just two examples of the stakes at play.
Some of them even try to exploit the greed of their own kind! Enter honeypots.
Honeypots are smart contracts designed to look like an easy target while in fact they are not. They look vulnerable to an unsophisticated attacker, but if he tries to “break it” he will loose his money instead. Hunting the hunter. Hacking the hackers!
Here is an interesting specimen our team spotted recently: 0x4ba0d338a7c41cc12778e0a2fa6df2361e8d8465.
pragma solidity ^0.4.10;
contract Ownable {address public Owner = msg.sender;function isOwner() returns (bool) {if (Owner == msg.sender) return true; return false;}}
contract ICO_Hold is Ownable {mapping (address => uint) public deposits;uint public openDate;address public Owner;
function() public payable { }
function setup(uint \_openDate) public {
Owner = msg.sender;
openDate = \_openDate;
}
function deposit() public payable {
if (msg.value >= 0.5 ether) {
deposits\[msg.sender\] += msg.value;
}
}
function withdraw(uint amount) public {if (isOwner() && now >= openDate) {uint max = deposits[msg.sender];if (amount <= max && max > 0) {msg.sender.transfer(amount);}}}}
Can you tell where is the catch?
In order to exploit this one an attacker has to deposit 0.5 ETH first. Next he is supposed to claim an ownership by calling setup()
incautiously left unprotected. After that he can devour entire balance by calling withdraw()
multiple times. Notice that amount withdrawn is never deducted from a balance recorded?
The real trick is having address public Owner
defined twice. Once in the Ownable
and second time in the primary contract. That is why calling setup()
won’t affect isOwner()
within withdraw()
method. An easy line to miss for a wanna be hacker in rush.
That was just one relatively uncomplicated example of a honeypot contract. There are so many of them in the wild:
Does it sound too easy and trivial? Here is a bitter story of a real ether lost: https://www.reddit.com/r/ethdev/comments/7x5rwr/tricked_by_a_honeypot_contract_or_beaten_by/ This stuff actually works!
However, I want to argue calling these smart contracts honeypots. Honeypots have been around for a long time. They are used by white hats to detect and prevent attacks, i.e. for good and not to steal somebody else’s money. This is a principal difference. These contracts are not made to prevent attacks, but rather to collect excise from less skillful hackers. So they need a different name. I would call them mousetraps.
It will be very interesting to check how many honeypots are published without verified source code. This can be a whole new level of the game.
Have you ever encountered honeypots? Do you think that hacking the hackers is ethical?
Originally published at www.unchained.team on August 24, 2018.