#37191 [BC-Insight] Unvalidated Field Names in Tuple ABI Parsing Causes Runtime Panic via reflect.StructOf
Submitted on Nov 28th 2024 at 03:23:27 UTC by @CertiK for Attackathon | Ethereum Protocol
Report ID: #37191
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 exists in the accounts/abi package where unvalidated fieldName from user-provided ABI definitions are used to construct struct types using reflect.StructOf. This can cause a panic when the invalid characters are included in the fieldName.
Vulnerability Details
In the type.go file of the accounts/abi package, the code dynamically constructs tuple types based on ABI component definitions as follow:
https://github.com/erigontech/erigon/blob/v2.60.10/accounts/abi/type.go#L158
case "tuple":
var (
fields []reflect.StructField
elems []*Type
names []string
expression string // canonical parameter expression
)
expression += "("
overloadedNames := make(map[string]string)
for idx, c := range components {
cType, err := NewType(c.Type, c.InternalType, c.Components)
if err != nil {
return Type{}, err
}
fieldName, err := overloadedArgName(c.Name, overloadedNames)
if err != nil {
return Type{}, err
}
overloadedNames[fieldName] = fieldName
fields = append(fields, reflect.StructField{
Name: fieldName, // reflect.StructOf will panic for any exported field.
Type: cType.GetType(),
Tag: reflect.StructTag("json:\"" + c.Name + "\""),
})
elems = append(elems, &cType)
names = append(names, c.Name)
expression += cType.stringKind
if idx != len(components)-1 {
expression += ","
}
}
expression += ")"
typ.TupleType = reflect.StructOf(fields)
typ.TupleElems = elems
typ.TupleRawNames = names
typ.T = TupleTy
typ.stringKind = expression
The fieldName is taken directly from the ABI component's Name without validation. However, the reflect.StructOf function requires that all field names be valid with the following check. Otherwise, the panic will rise.
https://github.com/golang/go/blob/master/src/reflect/type.go#L2205
It is worth noted a similar issue has been fixed in go-ethereum: https://github.com/ethereum/go-ethereum/pull/24932
Impact Details
Any program that invokes the vulnerable code will panic with an invalid field name.
References
https://github.com/golang/go/blob/master/src/reflect/type.go#L2205
https://github.com/ethereum/go-ethereum/pull/24932
Proof of Concept
Proof of Concept
We can reuse the test from go-ethereum to verify the issue:
Output:
Was this helpful?