This blog post provides an update on our results after the discovery of the storage corruption bug last week. In summary, the bug was much less serious than we initially thought. The small number of affected contracts that we have found is either the owner’s operation, or the feat can only cause a disturbance of the user interface and not in the real contractual logic. All the usable / DAPP contracts that we have examined can be set without having to upgrade the contract itself. Of course, please always check your contracts to be safe.
Following the discovery of the storage corruption bug in the solidity compiler and the awareness that it can have serious effects on contracts already deployed which cannot be updated, we have started to analyze how common the bug is and how the contracts can be treated.
We focused on contracts with the source code published on Etherscan because important or popular intelligent contracts generally have their source code published in order to gain the confidence of their users, who can then check the compilation. In addition, if the source code is not available, it is also much more difficult for an attacker to find an appropriate feat. Finally, contracts used in private (and therefore do not require publication of his source code) generally verify that they are called from a certain address, and therefore an attacker has no way of writing in his storage.
In order to automate the process of verifying all contracts on Etherscan, we have created a modified version of the solidity compiler which can automatically detect the trigger for the bug. This technique has already reduced the number of contracts potentially vulnerable to 167. We then manually checked these potential storage corruption contracts which would make them vulnerable to attacks.
It turns out that only ten contracts were vulnerable, so we were able to contact most of the owners / developers of contracts. Seven of the ten of these contracts can only be used by the owner in that they are authorized to modify certain parameters outside their authorized range, or authorized to unlock a previously locked contract. A contract can be used by non -privileged users but has other major faults in its design. The other two contracts have proven to be exploited by unavigiated users have provided no advantage if it is used or affected only the user interface.
Why only so few contracts are exploitable?
First of all, let’s define what we mean by “usable”:
The storage corruption bug can be used if it can be used to modify a storage variable in a way that would not be possible without the bug, and this modification has consequences on the behavior and the use of the intelligent contract. For example, we do not consider an usable contract in the following situations:
- The same account would be able to crush the variable in the same state of the contract by regular means.
- The crushing can only occur at the time of the construction (note that we did not check if the crushing occurred at that time).
- The crushing is only triggered in improbable situations where contractual logic has been broken anyway (for example, a 32 -bit counter which is incremented once by block, oveflows).
- The variables can be crushed which is not used in the intelligent contract and do not seem criticism, but can be part of the public interface.
Why is this critical bug exploitable only in so few cases?
It is a combination of the following factors that multiply and considerably reduce the probability of exploitability.
- Since small types provide only advantage in very rare cases, they are rarely used.
- Small guys must be adjacent to each other in storage – a single large guy between them prevents the bug from being triggered.
- State variables are often allocated one after the other, which removes corruption during the second assignment.
- The combination of “address” and “Bool” is the most common among the cases that remain, but here, the address variable is often an “owner” which is attributed from Msg.sender And therefore not usable. Even if the owner can be modified, the flag is often a flag which can be still defined by the owner by other means.
How to repair affected contracts
A large majority of usable contracts can only be used by the owner, the administrator or the developer of the contract, in particular if a single function which allows the owner to be modified. The feat allows a new climbing of privileges for the owner. In order to prevent the owner from taking advantage of this feat, a proxy contract can be installed between the owner and the affected contract. This proxy contract transmits the owner’s calls, but forbidden to call the useful functions. If calling the usable functions is always necessary, the proxy contract can prevent malicious data from being transmitted to the contract.
If you have specific questions or concerns about your contracts, please contact us on frosty.
An important friendly note from legal part
The declarations of this article are recommendations to resolve the storage corruption bug in the Solidity compiler. As you know, we work in an emerging and evolving technical space. The same elements that make this work exciting – innovation, impact, growing understanding of contracts – are the same people who make it risky. If you choose to implement the recommendations in this article and continue to participate, you must make sure to understand how it has an impact on your specific contract and you must understand that there are risks involved. By choosing to implement these recommendations, only you assume the risks of the consequences.