I recently started learning
Solidity, and I am interested in security aspects. Today, I encountered a very interesting blog article discussing security vulnerability in
Rust. At my level of understanding, other vulnerabilities being commented on here except for the
first and the
third one may not be the case for
Solidity, which gave me an impression that
Solidity has a stronger security character than
Rust. I wish that I can hear from other experts if my idea is not wrong. Please openly discuss the items below in the article, and please also suggest if there are more security considerations, in general, writing a contract in
1. Missing Ownership Check
Smart contracts commonly contain privileged functionality that should only be accessible to certain accounts. If this is the case, then a smart contract should verify that an account is trusted before running this privileged functionality.
All Solana accounts are owned by smart contracts–to this rule there is no exception. Only contracts are allowed to modify accounts’ data. It is the smart contract developers’ task to implement necessary authorization controls, including the verification of the transaction sender’s digital signature.
Account metadata struct in Solana includes the owner field that indicates the public key associated with that account’s owner. To validate that an account is trusted, the public key stored in its owner field should be checked against expected values.
Some Solana smart contracts use config or other utility accounts to store trusted data or the public key of an administrator’s account. Those accounts have to be provided by users running the smart contract and executing certain actions.
However, if a contract does not validate the owner of a utility account, it could be vulnerable to exploitation. An attacker could bypass access controls with a fake config account if the account’s owner isn’t verified to be as expected and trick the smart contract to perform privileged operations.
Instead of inherently trusting certain accounts, Solana smart contracts should verify that they are owned by the contract’s owner.
2. Lack of Signature Validation
For restricted functionality, checking that the public key of the calling account matches that of an authorized user is an important first step. However, an account can technically set its data to whatever it wants; it’s just data.
Verification occurs when the account signs an operation with the private key associated with that public key. If a smart contract fails to check that an operation is signed, then anyone can call that instruction as long as their account contains the correct public key.
Solana smart contracts should validate that an operation is signed with an appropriate private key before executing privileged functionality.
3. Integer Overflows and Underflows
Rust (and other programming languages) store values in fixed-size variables. This means that these variables can only hold a certain range of values. If an operation results in a value outside of this range, it creates an integer overflow or underflow.
In the debug mode, Rust will check for overflows and underflows, but this is not true in the release mode (which is used by the Solana BPF toolchain). If a value moves outside the range of values that a variable can support, it will wrap around.
An attacker can exploit this fact to evade validation of transfers of value. If a program checks that a + b < c and a and b are not added together in the transfer, then an attacker could choose the values of a and b to overflow the check. Later, when the transfer occurs, only one value is used, which means that it will not overflow and a large amount of value will be sent to the indicated address.
Integer overflows and underflows typically result from unsafe math and unsafe casts between variable types. If it uses checked versions of the arithmetic and cast operations, a smart contract will throw an error if an overflow/underflow occurs, causing the transaction to be canceled.
4. Failure to Validate External Programs
Smart contracts are designed to interact with one another and call functions from external programs. Solana’s design patterns state that programs to be invoked within a function should be passed to that function as an argument.
Function arguments may be under the user’s control, which means that an attacker could supply malicious inputs. By passing a lookalike program as an argument to a vulnerable function, an attacker could convince the smart contract to run that program (and sometimes even assume the calling program’s identity) instead of the one that they intended.
Like verifying accounts based on their public keys, smart contracts should verify the programs that they invoke based on their public keys. This verifies that the program is the one that the smart contract intended to invoke.
5. Missing Account Structure Validation
A Solana smart contract may define multiple different accounts for different purposes. These attacks can have different structures and contain different types of data.
Account data is passed to a Solana smart contract function as a byte array, which the recipient then deserializes based on the structure of the expected account type. This creates an opportunity for exploitation where a malicious user creates an account of one type and passes it to a smart contract function as an instance of another type of account.
A check of the ownership of the account would pass ownership checks if it was created by one of the contract’s own functions. However, the data associated with that account would be interpreted based on the perceived account type, which could allow the attacker to set certain values and pass checks.
This attack takes advantage of the fact that one type of account could be substituted for another. If an account’s data starts with an identifier unique to that type of account and that value is checked by the functions using that account, then this attack is not possible.
 Rob Behnke, 04.11.2022, https://halborn.com/how-to-hack-solana-smart-contracts-programs/
P.S. I believe this post is very relevant for us to openly discuss even though it does not contain even a single line of code.