Aurora Improper Input Sanitization Bugfix Review

Immunefi
Immunefi
Published in
5 min readSep 29, 2022

Summary

On June 10, an anonymous whitehat submitted a critical vulnerability to Aurora via Immunefi, which consisted of improper input sanitization.

The Aurora team quickly fixed the issue, and no user funds were lost.

Aurora then paid out a bounty of $1,000,000 in Aurora tokens, streamed linearly over a year.

Immunefi is pleased to have facilitated this responsible disclosure with our platform. Our goal is to make Web3 safer by incentivizing hackers to responsibly disclose bugs and receive clean money and reputation in exchange.

Before we go any further, we’d like to note that this bugfix review was written by Mustafa of Halborn, a top-tier DeFi security auditing firm. If you’d like to write bugfix reviews for Immunefi and get your firm’s name out there, send us an email at team@immunefi.com

Introduction: What is Aurora?

Before we explain what Aurora is, it would make more sense to first explain what the Ethereum Virtual Machine (EVM) is. The EVM is a global virtual machine built to compile and validate smart contracts (logic that allows the programmability of the Ethereum blockchain). This allows developers to build EVM-compatible smart contracts using the Solidity programming language locally without having to worry too much about the environment since the EVM takes care of making sure those smart contracts would deploy and run on the blockchain regardless of the development environment used by the developer.

A major drawback to the Ethereum blockchain is the high gas fees and transaction costs. Aurora provides a solution to this issue by creating an EVM that runs on the NEAR Protocol blockchain. This allows developers to build their contracts in Solidity, since it is the most popular smart contract development language, while benefiting from the low transaction costs and high throughput and scalability the NEAR blockchain provides.

The solution Aurora has built as an EVM implementation on NEAR is called the Aurora Engine, and it is implemented as a smart contract on the NEAR blockchain. That said, from NEAR’s perspective, it is just another smart contract in the ecosystem. However, that smart contract acts as a layer 2 blockchain by itself for EVM-compatible smart contracts.

ERC20, NEP-141, and the Aurora Engine

The ERC20 (Ethereum Request for Comments 20) is a standard for fungible tokens that was proposed back in 2015 for the Ethereum blockchain. The NEP-141 (NEAR Enhancement Proposal — 141) proposal is the equivalent of ERC20 for the NEAR protocol.

Since the Aurora Engine is an EVM built on NEAR that supports ETH as its base currency for transaction fees, it would make sense that the interchangeability of the two token standards is supported by the engine.

For example, the Aurora Engine implements ft_on_transfer(), which adds support for receiving NEP-141 fungible tokens to the EVM (remember, this is still after all a NEAR smart contract). The NEP-141 tokens transferred to the EVM are then converted into the equivalent ERC20 tokens amount and transferred to the user.

The implementation is as follows:

Notice the call to the receive_erc20_tokens() function on the engine with the &args parameter, which is an instance of NEP141FtOnTransferArgs whose implementation is as follows:

rust
NEP141FtOnTransferArgs {
pub sender_id: AccountId,
/// Balance can be for Eth on Near and for Eth to Aurora
/// `ft_on_transfer` can be called with arbitrary NEP-141 tokens attached, therefore we do not specify a particular type Wei.
pub amount: Balance,
pub msg: String,
}

The implementation of receive_erc20_tokens() is very complex. Fortunately, though, we do not have to care about most of it. Take a look at the following code snippet:

The function parses the message contents encapsulated in the msg field out of the args input value and makes sure it is a certain length. Next, the function parses the recipient’s address out of the message and ensures it is valid. It also checks if a fee that should be paid to the message relayer was also supplied in the message or not.

Then the function fetches the ERC20 token that corresponds to the NEP-141 that initiated the transfer. The logic looks like the following:

rust
let erc20_token = Address::from_array(unwrap_res_or_finish!(
unwrap_res_or_finish!(
get_erc20_from_nep141(&self.io, token),
output_on_fail,
self.io
)
.as_slice()
.try_into(),
output_on_fail,
self.io
));

The final step is the handling of fees. If the fees value is greater than 0, it is transferred from the recipient to the message relayer. Once that is done, the equivalent ERC20 amount of tokens is then minted to the recipient:

Vulnerability Analysis

Now comes the interesting part–the vulnerability in the logic explained in the previous section. As you may have noticed, the &args value is totally under the control of the attacker. A malicious user could perform the following step-by-step attack scenario:

1. Create a NEP-141 -> ERC20 mapping prior to carrying out the attack. This is a permissionless operation so the attacker faces no barriers.

2. Transfer their NEP-141 token (which is worthless) to their victim, specifying U64_MAX as the fee in the msg field of the args value. Their address will be that of the message relayer in this case since signer_account_id() will be the attacker’s NEAR account’s address.

3. Receive funds from the recipient to their NEAR account

At the time this issue was reported, this would have allowed an attacker to drain user funds at the frequency of 18.4 ETH per invocation.

Vulnerability Fix

The vulnerability was fixed by completely removing the logic that assigns a non-zero transaction fee. This is an effective solution for the issue, as the bridge’s front-end application never actually used the fee amount.

Acknowledgements

We would like to thank the anonymous whitehat for doing an amazing job and responsibly disclosing such an important bug. Big props also to the Aurora team who responded quickly to the report and patched it.

We’d like to give further thanks to Mustafa of Halborn for writing this bugfix review.

If you’d like to start bug hunting, we got you. Check out the Web3 Security Library, and start earning rewards on Immunefi — the leading bug bounty platform for web3 with the world’s biggest payouts.

And if you’re feeling good about your skillset and want to see if you will find bugs in the code, check out the bug bounty program from Aurora.

--

--

Immunefi
Immunefi

Immunefi is the premier bug bounty platform for smart contracts, where hackers review code, disclose vulnerabilities, get paid, and make crypto safer.