SlowMist: A Brief Analysis of the Security Risk of Uninitialized Storage Pointers in Solidity (Released in 2018)
This article was written by Thinking@SlowMist Security Team. Here is the source GitHub Link.
Introduction
Recently, we came across an article by SECBIT Labs discussing the issue of Beware! Solidity Vulnerabilities Can Easily Lead to Uncontrolled Contract States. Actually, this issue has been previously mentioned in the SlowMist Zone, where Pds and Keywolf translated a foreign article, which can be found on SlowMist’s GitHub.
In essence, it is about the security issue of Uninitialized Storage Pointers. In the EVM, data is stored as either storage or memory. The default type of local variables in functions depends on their own types. Uninitialized storage variables may point to other variables in the contract, thereby changing the values of those other variables. A common scenario is pointing to state variables, altering their values, and consequently leading to the emergence of vulnerabilities.
Analysis Process
Based on the introduction in the Solidity official manual and experimental results, we have drawn some conclusions and analysis.
It is important to note the local variables of struct, array, and mapping. The official manual mentions that local variables of these types are stored in storage by default. Therefore, these local variables may all have the same issue. (This article analyzes the Uninitialized Storage Pointer problem for struct and array, while no vulnerable cases have been found for mapping yet.)
When assigning values to local variables within a struct, they are stored as a reference.
Below is the vulnerable code. The struct is declared in the function but not initialized. According to the official documentation, struct in local variables is stored in storage by default. Therefore, by exploiting the Uninitialized Storage Pointers issue, p will be treated as a pointer and will point to slot[0] and slot[1] by default. Consequently, when assigning values to p.name and p.mappedAddress, the values of variables testA and testB will actually be modified.
Similarly, array also has the same issue. The following is the vulnerable code:
Solution
The correct solution to the Uninitialized Storage Pointers issue with struct is to initialize the declared struct by assigning a value. This can be done by creating a new temporary memory struct and then copying it to storage.
The correct solution to the Uninitialized Storage Pointers issue with arrays is to initialize the local variable x while declaring it.
The Solidity compiler development team is expected to fix the code with Uninitialized Storage Pointers issues in the next version (Solidity 0.4.25); otherwise, it will not compile properly.
Developers need to pay attention to the release of Solidity 0.4.25 and use it to write their code.
Lastly, this article does not cover the security issues and cases of uninitialized storage pointers in mapping. We look forward to researching and discussing these topics with fellow experts.
About SlowMist
SlowMist is a blockchain security firm established in January 2018. The firm was started by a team with over ten years of network security experience to become a global force. Our goal is to make the blockchain ecosystem as secure as possible for everyone. We are now a renowned international blockchain security firm that has worked on various well-known projects such as Huobi, OKX, Binance, imToken, Crypto.com, Amber Group, Klaytn, EOS, 1inch, PancakeSwap, TUSD, Alpaca Finance, MultiChain, O3Swap, etc.
Website:
https://www.slowmist.com
Twitter:
https://twitter.com/SlowMist_Team
Github:
https://github.com/slowmist/
