mirror of https://github.com/status-im/nim-eth.git
discv4: Fix assert on invalid RLP list in Neighbours message (#763)
The assert would occur when the rlp size of the a node in the nodes rlp list is incorrectly set too high and then the next `listElem` call for the next node will start from the incorrect data. When that data is not a list the assert in `listElem` will be triggered. Fixed by adding a `listLen` call which checks if it is a list. Added also more strictness by: - Checking if that list is of len 4, which it must be - raising immediatly on invalid IP length - raising immediatly on invalid public key / node id + test cases
This commit is contained in:
parent
dc092ca393
commit
aa92ad4f42
|
@ -220,6 +220,9 @@ proc recvNeighbours(
|
||||||
var neighbours = newSeqOfCap[Node](16)
|
var neighbours = newSeqOfCap[Node](16)
|
||||||
for i in 0 ..< sz:
|
for i in 0 ..< sz:
|
||||||
let n = neighboursList.listElem(i)
|
let n = neighboursList.listElem(i)
|
||||||
|
if n.listLen() != 4:
|
||||||
|
raise newException(RlpError, "Invalid nodes list")
|
||||||
|
|
||||||
let ipBlob = n.listElem(0).toBytes
|
let ipBlob = n.listElem(0).toBytes
|
||||||
var ip: IpAddress
|
var ip: IpAddress
|
||||||
case ipBlob.len
|
case ipBlob.len
|
||||||
|
@ -228,17 +231,14 @@ proc recvNeighbours(
|
||||||
of 16:
|
of 16:
|
||||||
ip = IpAddress(family: IpAddressFamily.IPv6, address_v6: toArray(16, ipBlob))
|
ip = IpAddress(family: IpAddressFamily.IPv6, address_v6: toArray(16, ipBlob))
|
||||||
else:
|
else:
|
||||||
error "Wrong ip address length!"
|
raise newException(RlpError, "Invalid RLP byte string length for IP address")
|
||||||
continue
|
|
||||||
|
|
||||||
let udpPort = n.listElem(1).toInt(uint16).Port
|
let udpPort = n.listElem(1).toInt(uint16).Port
|
||||||
let tcpPort = n.listElem(2).toInt(uint16).Port
|
let tcpPort = n.listElem(2).toInt(uint16).Port
|
||||||
let pk = PublicKey.fromRaw(n.listElem(3).toBytes)
|
let pk = PublicKey.fromRaw(n.listElem(3).toBytes).valueOr:
|
||||||
if pk.isErr:
|
raise newException(RlpError, "Invalid RLP byte string for node id")
|
||||||
warn "Could not parse public key"
|
|
||||||
continue
|
|
||||||
|
|
||||||
neighbours.add(newNode(pk[], Address(ip: ip, udpPort: udpPort, tcpPort: tcpPort)))
|
neighbours.add(newNode(pk, Address(ip: ip, udpPort: udpPort, tcpPort: tcpPort)))
|
||||||
d.kademlia.recvNeighbours(node, neighbours)
|
d.kademlia.recvNeighbours(node, neighbours)
|
||||||
|
|
||||||
proc recvFindNode(
|
proc recvFindNode(
|
||||||
|
|
|
@ -13,6 +13,7 @@ import
|
||||||
std/sequtils,
|
std/sequtils,
|
||||||
chronos, stew/byteutils, nimcrypto/keccak, testutils/unittests,
|
chronos, stew/byteutils, nimcrypto/keccak, testutils/unittests,
|
||||||
../../eth/common/keys, ../../eth/p2p/[discovery, kademlia, enode],
|
../../eth/common/keys, ../../eth/p2p/[discovery, kademlia, enode],
|
||||||
|
../../eth/rlp,
|
||||||
../stubloglevel
|
../stubloglevel
|
||||||
|
|
||||||
proc localAddress(port: int): Address =
|
proc localAddress(port: int): Address =
|
||||||
|
@ -108,6 +109,21 @@ procSuite "Discovery Tests":
|
||||||
# We currently do not raise on this, so can't really test it
|
# We currently do not raise on this, so can't really test it
|
||||||
# "0x03f847b841AA0000000000000000000000000000000000000000000000000000000000000000a99a96bd988e1839272f93257bd9dfb2e558390e1f9bff28cdc8f04c9b5d06b1846fd3aed7",
|
# "0x03f847b841AA0000000000000000000000000000000000000000000000000000000000000000a99a96bd988e1839272f93257bd9dfb2e558390e1f9bff28cdc8f04c9b5d06b1846fd3aed7",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
let invalidRlpData = [
|
||||||
|
# valid version: "0x04f8a5f89ef84d847f000001827661827669b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e34f84d847f000001827662827662b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e348479e7f252",
|
||||||
|
# Invalid rlp item length (for the individual node list), causing a next listElem to read wrong data.
|
||||||
|
"0x04f8a5f89ef856847f000001827661827669b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e34f84d847f000001827662827662b8403114ae2fe09b7a71d6693451c0d043df8315fb811e43c7b97ef2ff87409a2601b4425f92ffff80008417d66489cb1f8414d9dd4393ba16ebb455aa47345a222b8479e7f252",
|
||||||
|
# Invalid IP length in nodes
|
||||||
|
"0x04f8a4f89df84c837f0001827661827669b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e34f84d847f000001827662827662b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e348479e7f252",
|
||||||
|
# Invalid Public key in nodes
|
||||||
|
"0x04f8a5f89ef84d847f000001827661827669b840fbefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e34f84d847f000001827662827662b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e348479e7f252",
|
||||||
|
# Invalid Public key in nodes - too short
|
||||||
|
"0x04f8a4f89df84c847f000001827661827669b83fefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e34f84d847f000001827662827662b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e348479e7f252",
|
||||||
|
# nodes list len of 3 (removed port)
|
||||||
|
"0x04f8a2f89bf84a847f000001827661b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e34f84d847f000001827662827662b840ebefe173cab8832f6d6623f2a4d415959c1b80071e6af7d5986417d4bd07df19318b30d3d4fde75b025314ce22a523a714bef6c61838094e5d3640dccc6b9e348479e7f252"
|
||||||
|
]
|
||||||
|
|
||||||
let
|
let
|
||||||
address = localAddress(20302)
|
address = localAddress(20302)
|
||||||
nodeKey = PrivateKey.fromHex(
|
nodeKey = PrivateKey.fromHex(
|
||||||
|
@ -117,6 +133,10 @@ procSuite "Discovery Tests":
|
||||||
expect DiscProtocolError:
|
expect DiscProtocolError:
|
||||||
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
||||||
|
|
||||||
|
for data in invalidRlpData:
|
||||||
|
expect RlpError:
|
||||||
|
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
||||||
|
|
||||||
# empty msg id and payload, doesn't raise, just fails and prints wrong
|
# empty msg id and payload, doesn't raise, just fails and prints wrong
|
||||||
# msg mac
|
# msg mac
|
||||||
bootNode.receive(address, packData(@[], nodeKey))
|
bootNode.receive(address, packData(@[], nodeKey))
|
||||||
|
|
Loading…
Reference in New Issue