Immunefi Audit Competitions
Ethereum Protocol | Attackathon

#37300 [BC-Insight] Incorrect Encoding of Negative *big.Int Values in MakeTopics

Submitted on Dec 2nd 2024 at 00:47:26 UTC by @CertiK for Attackathon | Ethereum Protocol

  • Report ID: #37300
  • Report Type: Blockchain/DLT
  • Report severity: Insight
  • Target: https://github.com/ledgerwatch/erigon
  • Impacts:
    • (Specifications) A bug in specifications with no direct impact on client implementations

Description

Brief/Intro

A vulnerability has been identified in the MakeTopics function within the accounts/abi/topics.go file of the codebase. The issue stems from the incorrect encoding of negative *big.Int values when generating topics for contract events.

Vulnerability Details

Affected Codebase:
https://github.com/erigontech/erigon/tree/v2.61.0-beta1

In the MakeTopics function, the handling of *big.Int types is as follows:

https://github.com/erigontech/erigon/blob/v2.61.0-beta1/accounts/abi/topics.go#L45

			case *big.Int:
				blob := rule.Bytes()
				copy(topic[length.Hash-len(blob):], blob)

The rule.Bytes() method returns the absolute value of the *big.Int as a big-endian byte slice, disregarding the sign of the number. This means that negative integers are incorrectly encoded. For example, big.NewInt(-1).Bytes() returns [1], leading to the topic being encoded as 0x000...0001 instead of the correct two's complement representation 0xFFFF...FFFF.

https://github.com/golang/go/blob/master/src/math/big/int.go#L520

// Bytes returns the absolute value of x as a big-endian byte slice.
//
// To use a fixed length slice, or a preallocated one, use [Int.FillBytes].
func (x *Int) Bytes() []byte {
   // This function is used in cryptographic operations. It must not leak
   // anything but the Int's sign and bit size through side-channels. Any
   // changes must be reviewed by a security expert.
   buf := make([]byte, len(x.abs)*_S)
   return buf[x.abs.bytes(buf):]
}

Impact Details

The failure to correctly encode negative *big.Int values affects any functionality that relies on event topics generated by the MakeTopics function.

References

Proof of Concept

Proof of Concept

For simplicity, we can add the following test in TestMakeTopics
https://github.com/erigontech/erigon/blob/v2.61.0-beta1/accounts/abi/topics\\_test.go#L30

       {
           "support negative *big.Int types in topics",
           args{[][]interface{}{
               {big.NewInt(-1)},
           }},
           [][]libcommon.Hash{
               {libcommon.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")},
           },
           false,
       },

The test will raise the error:

--- FAIL: TestMakeTopics (0.00s)
   --- FAIL: TestMakeTopics/support_negative_*big.Int_types_in_topics (0.00s)
       /Users/xxx/erigon/accounts/abi/topics_test.go:144: makeTopics() = [[0x0000000000000000000000000000000000000000000000000000000000000001]], want [[0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff]]
FAIL
FAIL    github.com/erigontech/erigon/accounts/abi   0.508s
FAIL