Platform: Code4rena
Start Date: 10/03/2023
Pot Size: $180,500 USDC
Total HM: 6
Participants: 19
Period: 9 days
Judge: GalloDaSballo
Total Solo HM: 2
Id: 221
League: ETH
Rank: 4/19
Findings: 1
Award: $8,774.78
π Selected for report: 1
π Solo Findings: 0
π Selected for report: Jeiwan
Also found by: ronnyx2017
8774.7813 USDC - $8,774.78
User transaction can call system contracts directly, which shouldn't be allowed to not invoke potentially dangerous operations.
The DefaultAccount.executeTransaction executes a user transaction after it was validated. The function calls _execute under the hood. The _execute
function makes two different calls depending on the destination address of a transaction:
ContractDeployer
is called, it'll pass the call to the contract via the system call (ContractDeployer
is a system contract and can be executed only via system calls);EfficientCall.rawCall
.EfficientCall.rawCall
in its turn also makes two different calls:
msg.value
of the transaction is 0, it'll make a regular call.msg.value
is positive), it'll pass the call to the MsgValueSimulator
contract. MsgValueSimulator
is a system contract, thus the isSystem
flag will be set in the far call ABI (notice the true
in the last argument of _loadFarCallABIIntoActivePtr
). However, it'll also set the forward mask to 1 (the value of MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT). MsgValueSimulator
will extract the mask and will set the isSystemCall
flag to trueβit'll then pass the isSystemCall
flag to the subsequent call, making the call a system one.To sum it up, if a transaction calls a contract that's not ContractDeployer
and sends ETH, the call will be a system one, which will let it call the system contracts. However, users shouldn't be allowed to call system contracts directly to not invoke potentially dangerous operations. As per the documentation:
Some of the system contracts can act on behalf of the user or have a very important impact on the behavior of the account. That's why we wanted to make it clear that users can not invoke potentially dangerous operations by doing a simple EVM-like call. Whenever a user wants to invoke some of the operations which we considered dangerous, they must explicitly provide isSystem flag with them.
However, since most system contracts are harmless, there's no direct high severity impact on the system, thus I think the issue is a medium severity.
Manual review
In the EfficientCall.rawCall
function, consider setting the forward mask to 0. The behaviour of the function is similar to that of the msgValueSimulatorMimicCall
function from the bootloader:
MsgValueSimulator
contract is called, the isSystemCall
flag should be set only for this call;isSystemCall
flag should be forwarded by MsgValueSimulator
only if the destination contract is ContractDeployer
.It looks that the second part of the EfficientCall.rawCall
function was copied from the SystemContractsCaller.systemCall
function, which is intended to call system contracts and which sets the forward mask to 1 when calling MsgValueSimulator
. However, rawCall
shouldn't forward the isSystemCall
flag.
#0 - c4-judge
2023-03-23T13:48:20Z
GalloDaSballo marked the issue as primary issue
#1 - GalloDaSballo
2023-03-23T13:48:23Z
More detailed, making primary
#2 - miladpiri
2023-03-27T11:13:00Z
It is an issue, though realisticially most of the methods are non-payable.
#3 - c4-sponsor
2023-03-27T11:13:06Z
miladpiri marked the issue as sponsor confirmed
#4 - GalloDaSballo
2023-04-05T12:07:24Z
The Warden has shown a way to bypass the security checks that would prevent a end user to be able to call system contracts.
In lack of a loss of deposits, I agree with Medium Severity
#5 - c4-judge
2023-04-05T12:07:30Z
GalloDaSballo marked the issue as selected for report