EOS congestion 9/13/2019 and EOSPlay hack

What happens?

At 9/13/2019 the EOSPlay DApp was hacked. The hacker exploited a flaw of the implementation of the EOSplay Random Number Generator (RNG), which allows him to take away about 30,000 EOS from the EOSPlay smart contract.

NOTE 1: The attack is not related to the design of EOSIO but only to the design of this particular DApp.

NOTE 2: We do not have the source codes of the hacked contract. Everything described on this article is a set of assumptions made by smart-contract developers based on what we know about the smart-contracts and EOS. We can only observe the history of transactions at the time of the attack and, based on the results of these transactions, draw conclusions about the attack principle, design of the attacker’s contract and contract of attacked DApp.

If you found a mistake, something that I’m missing or any useful info that I should include into this article please contact me: https://t.me/Dexaran

Here are the results of the contract decompilation:

https://hackmd.io/u6yWyfFrRDieRFnjgmn9pA

How it happens?

What attacker did

(Source: Dexaran)

  1. Rented 1,2M of CPU and NET at EOSREX resource exchange. (This costs him ~300 EOS)

Theoretical explanation

Apparently EOSPlay’s RNG was built fully on-chain. The problem with the RNG is that it requires a source of entropy to generate a random number. There is no built-in source of entropy in EOS. EOSPlay developers decided to use future blocks as a source of entropy, because the user does not know what will happen in the future at the time of sending the transaction.

It turns out that the hacker could manipulate future transactions to send “losing” transactions into infinite loops, thus preventing them from being executed. ”Winning” transactions were left to be executed successfully.

There is a REX (resource exchange) in EOS. REX enables users to buy CPU and NET bandwidth and use it to power transactions.

A hacker rented 1,2 million CPU from REX to create thouthands of deferred transactions to the EOSPlay smart-contract which caused the network congestion. (Source: Michael Fletcher)

The attacker fills the queue with deferred transactions and waited until they are in the block where the bet is executed. Then he sent “losing” transaction into infinite loops. (Source: Michael Yeates)

These are hacker’s accounts:
https://eosflare.io/account/mumachayinmm https://eosflare.io/account/gotoworkhome https://eosflare.io/account/mumachayinm1 https://eosflare.io/account/mumachayinm2 https://eosflare.io/account/mumachayinm3
https://eosflare.io/account/mumachayinm4 https://eosflare.io/account/mumachayinm5

Apparently the hacker was trying to attack this DAPPS:
https://eosflare.io/account/eosplaybrand
https://eosflare.io/account/dswinnermach (this tx for example)
https://eosflare.io/account/dswinnerpool

What do we know?

Here are Daniel Larimer’s comments regarding the attack (source):

Owning and staking #eos gives users a prorata share of available bandwidth. When people don’t use their share it is redirected to others on a prorata basis. During heavy use users no longer receive this free benefit.

Lesson learned here is don’t design contracts that depend upon extra bandwidth available during uncontested mode. The eosplay contract should have a low cpu action to pause execution available to contract maintainers.

There were some statements that the attacker made it impossible for EOSPlay developers to stop the contract and interrupt the attack. For example this article (EOSGO) states the following:

Since the attacker caused the EOS network to become congested, the EOSPlay team was not able to block its smart contract operations. Therefore, the attacker managed to completely empty EOSPlay’s funds.

This is not true from what I know. The developers stopped the contract. Here is the transaction: https://eosflare.io/tx/2E32E80D77571D639535A830BA772A2D6F9FBAEB90A510CC5ACA6406A5EE1764

The EOSPlay conract was not emptied. Currently there are 148833.86 EOS remaining at the account’s balance: https://eosflare.io/account/eosplaybrand

What lesson should we learn from this?

  1. Smart-contract security is important. The fact that you can stop/upgrade the contract does not mean that you are 100% secure. It’s smart-contract developers’ responsibility to conduct security audits, but bounties and all the security-related operations to make ensure smart-contracts security. It’s way better to spend $20K on a professional security audit rather than have an exploit which will allow hackers to steal $100K.

What we know about the attackers contract?

The contract is located here: https://eosauthority.com/account?account=mumachayinmm

It uses 530 kb RAM so it is a decent contract. Not 10 lines of code.

There are the following public actions at the contract:

  • hi(num)

There are three public tables at the contract:

  • kkks — preserves a single row: id = 0 and flag = 0

Here you can find the contracts’ ABI: https://gist.github.com/Dexaran/e7f98e19f31077b549024b464cf45258