This article is a community submission. The author is Minzhi He, an auditor at CertiK.
Views in this article are of the contributor/author and do not necessarily reflect those of Binance Academy.
Blockchain bridges are critical in achieving interoperability in the blockchain space. Hence, bridge security is of paramount importance. Some common bridge security vulnerabilities include weak on-chain and off-chain validation, improper handling of native tokens, and misconfigurations. Testing the bridge against all possible attack vectors is recommended to ensure sound verification logic.
A blockchain bridge is a protocol connecting two blockchains to allow interactions between them. If you own bitcoin but want to participate in DeFi activity on the Ethereum network, a blockchain bridge enables you to do so without selling your bitcoin.
Blockchain bridges are fundamental to achieving interoperability within the blockchain space. They function using various on-chain and off-chain validations and therefore have different security vulnerabilities.
Why Is Bridge Security Critical?
A bridge usually holds the token a user wants to transfer from one chain to another. Often deployed as smart contracts, bridges hold a significant amount of tokens as the cross-chain transfers accumulate, making them lucrative targets for hackers.
In addition, blockchain bridges have a large attack surface as they involve many components. With that in mind, malicious actors are highly motivated to target cross-chain applications to drain large sums of funds.
Bridge attacks led to losses of over 1.3 billion USD in 2022, accounting for 36% of the year’s total losses, according to CertiK’s estimates.
Common Bridge Security Vulnerabilities
To enhance the security of bridges, it’s valuable to understand common bridge security vulnerabilities and test the bridges for them before launch. These vulnerabilities can be categorized into the following four areas.
Weak on-chain validation
For simple bridges, especially those designed for specific DApps, on-chain validation is kept to a minimum. These bridges rely on a centralized backend to execute basic operations like minting, burning, and token transfers while all verifications are performed off-chain.
In contrast, other types of bridges use smart contracts to validate messages and perform verifications on-chain. In this scenario, when a user deposits funds into a chain, the smart contract generates a signed message and returns the signature in the transaction. This signature serves as proof of the deposit and is used to verify the user's withdrawal request on the other chain. This process should be able to prevent various security attacks, including replay attacks and forged deposit records.
However, if there is a vulnerability during the on-chain validation process, the attacker can cause severe damage. For example, if a bridge uses Merkle tree to validate the transaction record, an attacker can generate forged proofs. This means they can bypass proof validation and mint new tokens to their account if the validation process is vulnerable.
Certain bridges implement the concept of “wrapped tokens.” For instance, when a user transfers DAI from Ethereum to BNB Chain, their DAI is taken from the Ethereum contract, and an equivalent amount of wrapped DAI is issued on the BNB Chain.
However, if this transaction isn’t properly validated, an attacker could deploy a malicious contract to route the wrapped tokens from the bridge to an incorrect address by manipulating the function.
The attackers also need victims to approve the bridge contract to transfer tokens using the function “transferFrom” to drain assets from the bridge contract.
Unfortunately, this is made worse because many bridges request infinite token approval from DApp users. This is a common practice that lowers gas fees but creates additional risks by allowing a smart contract to access an unlimited number of tokens from the user’s wallet. Attackers are able to exploit the lack of validation and excessive approval to transfer tokens from other users to themselves.
Weak off-chain validation
In some bridge systems, the off-chain backend server plays a critical role in verifying the legitimacy of messages sent from the blockchain. In this instance, we’re focusing on the verification of deposit transactions.
A blockchain bridge with off-chain validation works as follows:
Users interact with the DApp to deposit tokens into the smart contract on the source chain.
The DApp then sends the deposit transaction hash to the backend server via an API.
The transaction hash is subject to several validations by the server. If deemed legitimate, a signer signs a message and sends the signature back to the user interface via the API.
Upon receiving the signature, the DApp verifies it and permits the user to withdraw their tokens from the source chain.
The backend server must ensure that the deposit transaction it processes has actually occurred and was not forged. This backend server determines whether a user can withdraw tokens on the target chain and is, therefore, a high-value target for attackers.
The backend server needs to validate the structure of the transaction’s emitted event, as well as the contract address that emitted the event. If the latter is neglected, an attacker could deploy a malicious contract to forge a deposit event with the same structure as a legitimate deposit event.
If the backend server does not verify which address emitted the event, it would consider this a valid transaction and sign the message. The attacker could then send the transaction hash to the backend, bypassing verification and allowing them to withdraw the tokens from the target chain.
Improper handling of native tokens
Bridges take different approaches toward handling native tokens and utility tokens. For example, on the Ethereum network, the native token is ETH and most utility tokens adhere to the ERC-20 standard.
When a user intends to transfer their ETH to another chain, they must first deposit it into the bridge contract. To achieve this, the user simply attaches the ETH to the transaction, and the amount of ETH can be retrieved by reading the “msg.value” field of the transaction.
Depositing ERC-20 tokens differs significantly from depositing ETH. To deposit an ERC-20 token, the user must first allow the bridge contract to spend their tokens. After they’ve approved this and deposited the tokens into the bridge contract, the contract will either burn the user's tokens using the "burnFrom()" function or transfer the user's token to the contract using the "transferFrom()" function.
One approach to differentiate this is to use an if-else statement within the same function. Another approach is to create two separate functions to handle each scenario. Attempting to deposit ETH using the ERC-20 deposit function can result in the loss of these funds.
When handling ERC-20 deposit requests, users usually provide the token address as input to the deposit function. This poses a significant risk as untrusted external calls can occur during the transaction. Implementing a whitelist that only includes the tokens supported by the bridge is a common practice to minimize risk. Only whitelisted addresses are allowed to be passed as arguments. This prevents external calls as the project team has already filtered the token address.
However, issues may also arise when bridges handle native token cross-chain transfer, as the native token does not have an address. A zero address (0x000...0) is representative of the native token. This can be problematic since passing the zero address to the function can bypass the whitelist verification even if implemented incorrectly.
When the bridge contract calls “transferFrom” to transfer user assets to the contract, the external call to the zero address returns false since there is no “transferFrom” function implemented in the zero address. However, the transaction may still occur if the contract does not handle the return value appropriately. This creates an opportunity for attackers to execute the transaction without transferring any tokens to the contract.
In most blockchain bridges, a privileged role is responsible for whitelisting or blacklisting tokens and addresses, assigning or changing signers, and other critical configurations. Ensuring that all configurations are accurate is crucial, as even seemingly trivial oversights can lead to significant losses.
In fact, there has been an incident where the attacker successfully bypassed the transfer record verification due to a misconfiguration. The project team implemented a protocol upgrade a few days before the hack, which involved changing a variable. The variable was used to represent the default value of the trusted message. This change resulted in all messages being automatically deemed proven, thus allowing an attacker to submit an arbitrary message and pass the verification process.
How To Improve Bridge Security
The four common bridge vulnerabilities explained above demonstrate the challenges to ensuring security in an interconnected blockchain ecosystem. There are significant considerations for handling each of these vulnerabilities, and no single playbook applies to all of them.
For example, providing general guidelines to ensure an error-free verification process is challenging since each bridge has unique verification requirements. The most effective approach to prevent verification bypass is to thoroughly test the bridge against all possible attack vectors and ensure the verification logic is sound.
To summarize, it’s essential to perform rigorous testing against potential attacks and pay special attention to the most common security vulnerabilities in bridges.
Due to their high value, cross-chain bridges have long been a target for attackers. Builders can strengthen their bridges’ security by conducting thorough pre-deployment testing and engaging in third-party audits, reducing the risk of the devastating hacks that have plagued bridges over the last few years. Bridges are critical in a multi-chain world, but security must be a primary concern when designing and building an effective Web3 infrastructure.