#38277 [BC-Insight] Potential Out-of-Range Panic in `UnmarshalJSON()` of `HexOrDecimal256`
Submitted on Dec 29th 2024 at 23:39:47 UTC by @CertiK for Attackathon | Ethereum Protocol
Report ID: #38277
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
In the erigon-lib/common/math package, the type HexOrDecimal256
marshals big.Int into hex or decimal strings. Due to a mishandling of the slice index in the method UnmarshalJSON()
, it would possibly lead to an out-of-range panic if this method is invoked with a certain value.
Vulnerability Details
Affected Codebase: https://github.com/erigontech/erigon/tree/v3.0.0-alpha7
The function UnmarshalJSON()
is utilized to parse hex or decimal string into big.Int.
https://github.com/erigontech/erigon/blob/v3.0.0-alpha7/erigon-lib/common/math/big.go#L61
func (i *HexOrDecimal256) UnmarshalJSON(input []byte) error {
if len(input) > 0 && input[0] == '"' {
input = input[1 : len(input)-1]
}
return i.UnmarshalText(input)
}
The condition len(input) > 0 && input[0] == ' " '
is intended to ignore the first quote ' " ' if it exists as the first element of the input.
However, this check is not effective. In case that the input only contains the quote ' " ' , then the input length is 1, so the condition is satisfied, which leads to the out-of-range panic when taking the slice input[1:0]
.
In fact, the check should be len(input) > 1 && input[0] == ' " '
.
Impact Details
Though the type HexOrDecimal256 has been utilized in multiple places of the current codebase, for example,
https://github.com/erigontech/erigon/blob/v3.0.0-alpha7/core/blockchain.go#L71
type EphemeralExecResult struct {
StateRoot libcommon.Hash `json:"stateRoot"`
TxRoot libcommon.Hash `json:"txRoot"`
ReceiptRoot libcommon.Hash `json:"receiptsRoot"`
LogsHash libcommon.Hash `json:"logsHash"`
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
Receipts types.Receipts `json:"receipts"`
Rejected RejectedTxs `json:"rejected,omitempty"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
StateSyncReceipt *types.Receipt `json:"-"`
}
we are not aware of the potential attack vector and it may not be exploitable at this moment. Due to the potential node crash if it’s triggered implicitly or by future update, it’s recommended to fix it.
References
https://github.com/erigontech/erigon/tree/v3.0.0-alpha7
Proof of Concept
Proof of Concept
We provide the following simple test case by setting the input as the quote ' " ' .
package math
import (
"bytes"
"encoding/hex"
"math/big"
"testing"
"github.com/erigontech/erigon-lib/common"
)
func TestHexOrDecimal256UnmarshalJSON(t *testing.T) {
input := []byte{'"'}
var num HexOrDecimal256
_ = num.UnmarshalJSON(input)
}
The test result shows the out-of-range panic could be triggered in the method UnmarshalJSON()
with input ' " ' .
=== RUN TestHexOrDecimal256UnmarshalJSON
--- FAIL: TestHexOrDecimal256UnmarshalJSON (0.00s)
panic: runtime error: slice bounds out of range [1:0] [recovered]
panic: runtime error: slice bounds out of range [1:0]
goroutine 21 [running]:
testing.tRunner.func1.2({0x5a8b880, 0xc0000b8198})
/Users/***/go/pkg/mod/golang.org/[email protected]/src/testing/testing.go:1632 +0x230
testing.tRunner.func1()
/Users/***/go/pkg/mod/golang.org/[email protected]/src/testing/testing.go:1635 +0x35e
panic({0x5a8b880?, 0xc0000b8198?})
/Users/***/go/pkg/mod/golang.org/[email protected]/src/runtime/panic.go:785 +0x132
github.com/erigontech/erigon-lib/common/math.(*HexOrDecimal256).UnmarshalJSON(0xc000055f50?, {0xc00009ab28?, 0x151219ae47ae7?, 0x2a697f88?})
/Users/***/immunefi/erigon/erigon-lib/common/math/big.go:63 +0x48
github.com/erigontech/erigon-lib/common/math.TestHexOrDecimal256UnmarshalJSON(0xc0000bc9c0?)
/Users/***/immunefi/erigon/erigon-lib/common/math/big_test.go:34 +0x46
testing.tRunner(0xc0000bc9c0, 0x5aa1418)
/Users/***/go/pkg/mod/golang.org/[email protected]/src/testing/testing.go:1690 +0xf4
created by testing.(*T).Run in goroutine 1
/Users/***/go/pkg/mod/golang.org/[email protected]/src/testing/testing.go:1743 +0x390
Process finished with the exit code 1
Was this helpful?