Full Report
The delegateCall() function in Solidity is used to share the state between two contracts. The msg.value and msg.sender are shared when using this call. In the context of native contracts or functions emitting events, this has weird consequences though. In a different bug in the Aurora Engine, an abuse of this was found to make a delegateCall to an event emitter. Then, an offchain listener would add the funds to this user account. Since the msg.value was never actually sent to the contract, this essentially prints money. What else could go wrong with this? An interesting note is that the delegateCall() user is preserved the original user and NOT from the actual caller. Moonbeam and Moonriver are EVM compatible platforms. The native tokens, MOVR and GLMR, are precompiled ERC-20 contracts. When making calls to EVM related functions, it preserves the msg.sender for the call. So, what's the actual issue? The msg.sender preservation can be abused to perform an action as another user! Simply calling something with delegateCall() will preserve this, allowing the msg.sender to be the actual user on calls to other contracts. Currently, we still need a way to get the user to execute our code. This could be done via a phishing attack to execute a contract, but could be hard to do. In reality, all we need is a callback in our contract to be hit. What has callbacks? Flash loan providers! This could have been used to steal 12M without any user interaction. They also found a callback on a protocol called Glimmer. Although there is not too much being stored in the native MOVR contract, the amount deposited is consider collateral from the lending protocol. So, the steps of deposit, borrow, transfer and bad debt can be used over and over again to steal all of the funds from the contract! delegateCall() is a dangerous function in the EVM. From user impersonation to logs to the older days of malicious calls, the consequences of it need to be well audited. Good find!
Analysis Summary
# Vulnerability: Arbitrary User Impersonation via `delegateCall` on EVM Platforms with Native Token Precompiles
## CVE Details
- CVE ID: Not explicitly provided in the summary, but relates to a critical design flaw reported for the Aurora Engine.
- CVSS Score: Not explicitly provided. Severity is implied as **Critical** given the potential for stealing large amounts of funds ($12M mentioned, 70,000 ETH mentioned across related findings).
- CWE: CWE-843: Access of Object Referenced by a Deleted Pointer (Potentially related to unexpected state/sender manipulation, or CWE-20/CWE-749 if viewed as improper access control/permission bypass).
## Affected Systems
- Products: Aurora Engine (Layer 2 EVM solution built on NEAR protocol), Moonbeam, and Moonriver (EVM compatible platforms).
- Versions: Specific vulnerable versions are **not detailed**. The vulnerability implies issues with how `delegateCall` interacts with native token precompiled contracts (like ERC-20 wrappers for GLMR/MOVR) on these platforms.
- Configurations: Using `delegateCall` where the target is a contract that emits events or interacts with native token precompiles, especially within callback functions (e.g., in flash loan protocols).
## Vulnerability Description
The vulnerability stems from the specific preservation behavior of `msg.sender` when `delegateCall` is used on EVM platforms (like Moonbeam/Moonriver) that use precompiled ERC-20 contracts for their native tokens (MOVR, GLMR).
When `delegateCall` is used:
1. The state is shared between the calling contract and the target contract.
2. Crucially, when calling native/precompiled functions, `msg.sender` is **preserved** as the original user who initiated the external call sequence, rather than being set to the contract executing the `delegateCall`.
This allows an attacker (or vulnerable contract logic) to use `delegateCall` to execute arbitrary code *as* the legitimate `msg.sender`, even if the execution path involves an intermediary contract (like a flash loan protocol callback). If the execution path hits a callback function in a lending protocol, the malicious logic can execute arbitrary actions (deposit, borrow, transfer) while appearing to originate from the legitimate user/protocol, leading to fund drainage (e.g., stealing collateral).
## Exploitation
- Status: **Proof of Concept (PoC) likely exists/was demonstrated.** The text explicitly mentions an attack path that "could have been used to steal 12M without any user interaction" by hitting a callback in a lending protocol.
- Complexity: **Medium to Low** once the path (a callable function in a dependent protocol, like a flash loan callback) is identified.
- Attack Vector: **Network** (remote transaction).
## Impact
- Confidentiality: Minimal directly, primarily related to the execution context.
- Integrity: **High**. Allows unauthorized state changes and asset transfers via user/protocol impersonation.
- Availability: **High**. Can drain funds from lending protocols if exploited against collateral positions.
## Remediation
### Patches
- Specific vendor patch details are **not provided**. The vulnerability was reported and presumably fixed by the Aurora/Moonbeam teams following disclosure. Users must check vendor advisories for specific version updates.
### Workarounds
- Avoid using `delegateCall` when interacting with contracts that rely on strict `msg.sender` context, especially if the target is a system contract or a protocol utilizing callbacks, unless the context handling is explicitly controlled and audited.
- For lending protocols, ensure that callback functions rigorously verify the identity and context of the caller, even when interacting with delegated calls or cross-chain message passing mechanisms.
## Detection
- Indicators of Compromise: Unusually high number of transactions originating from legitimate user accounts executing protocol functions that involve cross-contract delegate calls, especially concerning native asset movements or lending positions.
- Detection Methods and Tools: Deep transaction tracing tools are required to analyze the origin of `msg.sender` during `delegateCall` execution sequences, comparing the initial transaction sender with the sender used in subsequent calls/state changes. Custom monitoring for unexpected state changes within native token precompiles initiated via delegation is key.
## References
- Related Disclosure: Researcher **pwning.eth** reported a critical bug in the Aurora Engine, leading to significant bug bounties.
- Vendor Advisories: Users must consult **Aurora Engine, Moonbeam, and Moonriver** official security announcements.