An Incorrect Check Of EOS Transaction Status Will cause “false-top-up” Valunerability
by yudan@SlowMist Security Team
Yesterday (March 10, 2019), EOS Vegas Town (contract account: eosvegasgame) was attacked and lost thousands of EOS. The SlowMist Security team captured the attack in time and synchronized it to the relevant exchanges and project parties. There is no identical case before this attack, but it can be classified as one of the “false top-up” attack categories. The following is a detailed analysis of the attack case by the SlowMist Security team.
According to the analysis of the SlowMist Security team, the attacker’s account is “fortherest12”. The SlowMist Security team queried “fortherest12” through eosq and found that the account executed a large number of error transactions.
Looking at any of these transactions, you can see that the failure type is hard_fail
This immediately reminds me of a paper I wrote not long ago about the attack methods of EOS blacklist(https://medium.com/@slowmist/roll-back-attack-about-blacklist-in-eos-adf53edd8d6). Though the attack method is difference , the principle is similar, that is, the state of receiving transactions is not analyzed.
There are two key points in this attack: “hard_fail”, and “delay”. It can be seen that the “delay” in the above picture has reached 2 hours. A detailed analysis of each of the points will follow.
Refer to the official development documentation(https://developers.eos.io/eosio-nodeos/docs/how-to-monitor-state)
There are two types of fail, soft_fail and hard_fail. Soft_fail is common. In general, soft_fail is triggered if eosio_assert is executed within the contract. The official documentation for soft_fail is: ` objective error and error handler execution ` .
Take the example of eosio_assert in the contract.
eosio_assert(0,”This is assert by myself”);
The fail of above example belongs to the objective. When an error occurs, the error handler executes correctly, and the content of the following prompt ` This is assert by myself `is printed by the error handler.
So what is hard_fail? The official documentation for hard_fail: ` objective error and error handler not executed correctly `. Simply put, there is an error but no error handler is used to handle the error. For example, if you use onerror capture processing but no onerror is caught, it will be hard_fail.
We have already understood the difference between hard_fail and soft_fail. The next question is: How to execute? Traditional error throws are thrown using eosio_assert , so there aren’t many chances of encountering hard_fail. How to throw a hard_fail error?
Move to the next key point — `delay`.
By observing, it can be known that “fortherest12” is a normal account, and general delay transactions are issued through contracts. In fact, the transaction can be delayed by a parameter setting in cleos, and even a non-contracted account can execute a delayed transaction. However, this kind of transaction is different from the eosio_assert issued by the contract, and there is no error handling. It will become hard_fail as described in the official documentation.
And the most important thing is that hard_fail will record on the chain.
According to the explanation of jerry @eoslive wallet, this attack is related to the mechanism of EOS. When the delay time of a transaction is not set to 0, it will not immediately verify whether the execution is successful. The processing of delayed transaction is push_schedule_transaction, and when the delay time of transaction is 0, it will directly push_transaction. There is a difference between the two processing mechanisms.
Why Vegas Town was attacked
The reason for this attack is that the project side only judged the existence of trx, but did not verify the status status of trx, which led to the success of this attack.
How to avoid
When the project side draws the prize, it should pay attention to the execution status of the bet order. on top of the judgment of whether the transaction exists,it should also be judged whether the bet order was successfully executed. As shown below.
Error type reference that causes object fail: https://eos.live/detail/16715
Official development documentation: https://developers.eos.io/eosio-nodeos/docs/how-to-monitor-state-with-state-history-plugin
Roll Back Attack about replay in EOS:https://medium.com/@slowmist/roll-back-attack-about-blacklist-in-eos-adf53edd8d69