Fastwin Hack Explained: Block.one Releases Stealthy Patches Against Critical Flaws
On 12/05/2018, the newly released EOS gambling DApp, Fastwin, was attacked by hackers. Blockchain security firm PeckShield detected and reported this hack in real time. Based on the analyzed data, between 03:18 AM and 04:15 AM, the hacker account named ha4tsojigyge attacked the Fastwin contract fastwindice3 124 times and got 1,929.71 EOS back. From further analysis by PeckShield researchers, the newly identified inlineReflex attacks were launched by the hacker to exploit the buggy logic for checking the caller of the contract.
Until November 2018, PeckShield had reported more than 27 EOS DApps security incidents including fake EOS attacks, random number loopholes, etc. While these attacks are evolving, the non-critical Fastwin hack revealed a critical vulnerability inside the EOSIO software — no permission check while performing self-addressed calls in a contract.
As shown in Figure 1, PeckShield researchers reported the critical vulnerability (CVE-2018-20163) immediately to Block.one via HackerOne. Block.one accepted the submission and told us that another research group independently reported the problem before. On 12/13/2018, the flaw was patched, followed by the stealthy patches for v1.5.1 and v1.4.5 which were released one day after. From our verification results, those patches fixed the bug perfectly, which avoids further attacks and possible financial loss.
To explain the details of inlineReflex, let’s start from a normal EOS transfer.
As shown in Figure 2, the player calls the system contract eosio.token to transfer EOS to the game contract. Then, the eosio.token contract sends out two transfer notices to the player account and the game contract account respectively by require_receipt(). When the game contract receives the notice, the dispatcher apply() is triggered before the transfer() handler is later invoked.
In Figure 3, the attacker ha4tsojigyge deployed a contract with a check() function which has the identical name to the function in the game contract. After a successful EOS transfer for starting the game, the attacker tricked the game contract to get the jackpot by herself.
Specifically, the attacker sends an inline action to herself in the pushck() function. The inline action is then handled by check() which sends a notice to the check() function of the game contract via require_recipient(). Now, since the dispatcher apply() in the game contract fails to screen out the notice, check() of the game contract is invoked — the attacker gets the jackpot.
The attacker exploited the buggy permission checking logic while performing self-addressed inline calls to impersonate fastwindice3. With the privileges of fastwindice3, the require_auth() check in the privileged check() function in the game contract which controls the jackpot could be bypassed.
As mentioned above, the account of the inline action info was ha4tsojigyge instead of the game contract fastwindice3. Therefore, if the game contract could check this and filter out the malicious notice in the dispatcher apply(), the attack would fail. In Figure 4, the standard apply() implementation handles this issue perfectly. Based on that, PeckShield suggests all developers to carefully check the caller of the function if a customized apply() is used.
Last but not the least. This is a critical EOS infrastructure flaw which allows an attacker to impersonate any account while sending inline actions. However, the patch against this bug leads to a compatibility problem. For example, when a contract performs an inline action but the actor is not the contract itself, the whole transaction would fail. According to the patch, this compatibility problem could be further fixed by granting the eosio.code permission to the actor.
PeckShield Inc. is a leading blockchain security company with the goal of elevating the security, privacy, and usability of current blockchain ecosystem. For any business or media inquires (including the need for smart contract auditing), please contact us at telegram, twitter, or email.