Platform: Code4rena
Start Date: 01/03/2024
Pot Size: $60,500 USDC
Total HM: 4
Participants: 18
Period: 21 days
Judge: Lambda
Total Solo HM: 3
Id: 344
League: POLKADOT
Rank: 11/18
Findings: 1
Award: $69.85
π Selected for report: 0
π Solo Findings: 0
π Selected for report: Cryptor
Also found by: 0xTheC0der, Bauchibred, Daniel526, XDZIBECX, ihtishamsudo, zhaojie
69.8535 USDC - $69.85
The put_sidevm_code function within the specified pallet allows for the storage of wasm bytecode associated with a given owner account. and this function computes a fee based on the size of the bytecode plus a static item deposit fee. However, there is no explicit check or limit on the maximum size of the bytecode vector (Vec<u8>) that can be stored. Consequently, this oversight facilitates a potential attack vector where a malicious user could upload excessively large wasm binaries, leading to unchecked resource consumption. Such actions could significantly degrade blockchain performance due to storage exhaustion, increase operational costs for node operators, and potentially lead to a denial-of-service condition.
pub fn put_sidevm_code( owner: T::AccountId, code: Vec<u8>, ) -> Result<T::Hash, DispatchError> { let hash = T::Hashing::hash(&code); let bytes = code.len() + hash.as_ref().len(); let fee = Self::deposit_per_byte() .saturating_mul(BalanceOf::<T>::saturated_from(bytes)) .saturating_add(Self::deposit_per_item()); Self::pay(&owner, fee)?; <SidevmCodes<T>>::insert(hash, WasmCode { owner, code }); Ok(hash) }
A malicious actor could exploit this vulnerability by repeatedly uploading very large wasm binaries to the blockchain. Since there's no explicit limit on the code size that can be stored, these actions could lead to significant storage consumption on nodes participating in the blockchain network.
class MockBlockchain: def __init__(self): self.storage = {} self.fee_schedule = {'deposit_per_byte': 1, 'deposit_per_item': 100} self.total_fees_collected = 0 def put_sidevm_code(self, owner, code): """ Simulates storing wasm code in the blockchain storage. """ code_size = len(code) fee = self.calculate_fee(code_size) # Simulate fee payment (here, simply adding to a total) self.total_fees_collected += fee # Store the code if fee payment is successful self.storage[owner] = code print(f"Stored code of size {code_size} bytes for owner '{owner}' with fee {fee}") def calculate_fee(self, code_size): """ Calculates the fee based on the size of the code. """ return self.fee_schedule['deposit_per_byte'] * code_size + self.fee_schedule['deposit_per_item'] # Create a mock blockchain instance mock_blockchain = MockBlockchain() # Define a list of code sizes to test, illustrating the lack of a size check code_sizes = [10, 100, 1000, 10000, 100000, 1000000, 10000000] for size in code_sizes: # Generate dummy code of specified size dummy_code = b'a' * size mock_blockchain.put_sidevm_code("Alice", dummy_code) print(f"Total fees collected: {mock_blockchain.total_fees_collected}")
as result : the Codes of varying sizes, ranging from 10 bytes to 10,000,000 bytes, were stored successfully for a single owner, 'Alice'. With each increase in code size, the fee calculated and collected also increased proportionally, based on the simplistic fee calculation model (1 unit per byte of code plus a flat fee of 100 units). The test concluded with a total of 11,111,810 units collected in fees, reflecting the cumulative cost of storing all the provided codes.
manual review
need a checks on the size of the wasm bytecode being uploaded through the put_sidevm_code function. Establish a maximum allowable size for wasm binaries that balances the need for legitimate functionality with the prevention of abuse
Other
#0 - c4-pre-sort
2024-03-25T07:55:29Z
141345 marked the issue as insufficient quality report
#1 - 141345
2024-03-25T07:55:34Z
wasm bytecode size invalid, the attacker pays the fee
#2 - c4-sponsor
2024-03-26T01:09:31Z
kvinwang (sponsor) acknowledged
#3 - kvinwang
2024-03-26T07:30:57Z
wasm bytecode size invalid, the attacker pays the fee
Correct. And there is a size limit check on-chain. But an additional check in the pink-runtime is a nice to have feature. Better as a QA level.
#4 - c4-sponsor
2024-03-26T07:31:03Z
kvinwang (sponsor) confirmed
#5 - c4-sponsor
2024-03-26T07:54:56Z
kvinwang marked the issue as disagree with severity
#6 - c4-judge
2024-03-27T13:44:01Z
OpenCoreCH changed the severity to QA (Quality Assurance)
#7 - c4-judge
2024-03-27T18:22:40Z
OpenCoreCH marked the issue as grade-b