Attackathon _ Fuel Network 32388 - [Smart Contract - Low] Buffer overflow in EncodeBufferAppend intr
Submitted on Thu Jun 20 2024 03:02:23 GMT-0400 (Atlantic Standard Time) by @anatomist for Attackathon | Fuel Network
Report ID: #32388
Report type: Smart Contract
Report severity: Low
Target: https://github.com/FuelLabs/sway/tree/7b56ec734d4a4fda550313d448f7f20dba818b59
Impacts:
Incorrect sway intrinsics leading to fuel heap buffer overflow
Description
Brief/Intro
Forgetting to resize the allocated buffer in __encode_buffer_append
causes fuel-vm
heap buffer overflow.
Vulnerability Details
The __encode_buffer_append
intrinsic powers AbiEncoding of sway builtin type. The Buffer
is initialized through __encode_buffer_empty
, and then passed along to __encode_buffer_append
to append new data to the encoding buffer.
The capacity of the buffer is initialized to 1024 bytes in __encode_buffer_empty
. In a perfect world, we'd resize the buffer if the encoded data length ever grows above this limit. However, __encode_buffer_append
does not do this. It blindly appends new data to the buffer
without ever checking the encode data length against buffer capacity.
This eventually leads to a heap buffer overflow.
Impact Details
The impact of this bug is pretty interesting in the way that the caller could unknowingly corrupt their own memory while performing a contract call. This may sound useless at first, since the caller has full control over its memory, but if we think about it carefully, there are cases where it could become impactful.
For example, a cunning attacker may deploy contracts
similar in structure to the fuel-bridge
, which requires the inputs
to come from a predicate
and have the predicate
verify the script
calling the contract
. This way, the attacker can easily control the caller code. Then by carefully crafting the script, it is possible to have an innocent looking part of it that calls a contract
function with large arguments. During encoding of the large arguments, a heap overflow happens, and overwrites either the method name or other important data stored on the heap, causing unexpected changes to the script execution flow. This is how the bug can be used to produce code to deceive users, and launch attacks such as rug-pulls by changing calls to airdrop
contract method into donate
contract method.
Aside from the fancy attacks, the normal contract not working impact as with all compiler bugs also applies.
References
https://github.com/FuelLabs/sway/blob/4b4fb53eb2ef3390a0186a7048b060ff8e973a15/sway-core/src/ir_generation/function.rs#L1510
https://github.com/FuelLabs/sway/blob/4b4fb53eb2ef3390a0186a7048b060ff8e973a15/sway-core/src/ir_generation/function.rs#L1815
Proof of concept
Proof of Concept
The encoded argument size of large_args
function is 2048 bytes plus 40 bytes for the CONTRACT_ID
and method name pointer, which is more than the capacity of the buffer and causes a buffer overflow. The contract method name gets overwritten during the buffer overflow, and causes the contract call to fail. If we reduce the total length of arguments to less than 1024 bytes, the contract call will succeed.
Writing rug-pull scripts for the attack idea mentioned in the impact section is not trivial, but I think it should be obvious that it is possible with the heap overflow.
Last updated