#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
https://github.com/erigontech/erigon/blob/v2.61.0-beta1
https://github.com/ethereum/go-ethereum/pull/28764/
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
Was this helpful?