On November 15-16, Moscow hosted the annual cyber battle The Standoff, which brought together the best teams of defenders and attackers. As part of the global information security conference, there was an NFT Hacking Competition called The Standoff Digital Art. We invited well-known digital artists to use their NFT works as targets for hacking. For the competition, we have prepared a smart contract of the ERC1155 standard for our collection. Each of the NFTs in the collection (there were 6 in total) was owned by a specially prepared vulnerable smart contract. With the successful exploitation of each of the smart contracts, the attacker received possession of the NFT (in the test network). There was also a cash prize for every successful hack. So what were the vulnerabilities?
In a smart contract we see three external functions: mint(), allowMinting() and addToWailist(). The goal is to force the smart contract to do the NFT transfer via the mint() function, however, in the constructor, the can mint variable is declared as false. To unlock the mint() function, the allowMinting() function is present, however, it is available only to the owner of the smart contract. What to do? If we carefully examine the third addToWailist() function, we will see that it declares an uninitialized dynamic list of addresses. In the Solidity language, if you do not assign any value to complex data types such as an array, mapping, or struct during initialization, then when using the “storage” keyword, the variable will simply overwrite the first storage slot of the smart contract. Truth, Solidity developers did not leave this “feature” of the language unattended and fixed the compiler 4 years ago so that an error would be returned in such cases. However, the compiler does not always see the overwriting of the NFT storage.
Impluse reports news on the latest technology, science, and business developments, their interactions with other industries.