Skip to content

p2p: An attacker with a single IPv6 lease or /24 subnet can insert himself in all nodes' address books ~10000 times #4846

@melekes

Description

@melekes

This security vulnerability was originally reported on Hackerone by itsunixiknowthis.


The structure of the address book of a node is as follows:
There are 2 lists of "buckets": Old buckets and New buckets.
There are 64 Old buckets and 256 New buckets.
Old peers who are somewhat more trustworthy or have been witnessed doing actual useful work go in the Old buckets and have certain privileges above New peers.
Each bucket has 65 addresses.
When a node wants to add a new address to its address book, the IP address is hashed to one of the 256 New buckets. The address is then placed in that New bucket, knocking out one addresses if necessary.

The function to hash the IP address to choose a bucket is called groupKey in p2p/pex/addrbook.go.
There are a few special considerations:
It is cheaper to buy a block of IPs (like 1.2.3.0/24) than random unrelated IPs (like 5.7.1.2 and 3.6.8.3). So groupKey treats an entire /16 block as a group - all addresses in the same /16 will have the same hash.
In IPV6, any user, even a home user should own at least 2^64 addresses. It's even easy to get bigger ranges. So groupKey treats anything in the same /32 as a single group.
And there are various other edge cases it handles.
groupKey indeed does all this. It converts an IP like 1.2.3.4 to 1.2.3.4/16 (represented by a 2 field Go struct). But it's supposed to return a bitmasked string, such as "1.2.0.0". But it doesn't work. Instead of converting 1.2.3.4 to "1.2.0.0", it converts it to a string like "1.2.3.4/16". So an attacker can simply buy a /24 block and get 256 groups instead of 1. Or on ipv6 he can use any connection whatsoever and have 2^64 groups. However IPv6 is still not supported everywhere so maybe a better route for the attacker is to buy a /24 ipv4 block.

If a node has less than 1000 peers in its address book, it will ask a random node its connected to for a peer list (only from outbound peers, not inbound).
Nodes maintain 10 outbound connections at all times.
When a node serves a peerlist request, it randomly samples from all its nodes. Since there are 65256=16640 New slots and only 6564=4160 Old slots, the attacker's nodes will practically always dominate.

All of the above, coupled with the fact that an attacker can replace all 65 entries in a bucket with a single of his IP addresses but different IDs (essentially, public keys), means an attacker can very cheaply dominate the network from a small number of IPv4 addresses (or a single IPv6 block).

Presumably the same attack can be done against the Old buckets given sufficient time, but we have not verified this.

If an attacker sees that a node makes 10 connections to his nodes, he knows he can start certain attacks such as an Eclipse attack against that target.

Impact

An attacker can cheaply insert himself multiple times in every node on the network (eventually, all nodes will have multiple concurrenct connections to the attacker's nodes)
Attacker may be able to use undue influence to execute certain attacks such as an Eclipse attack

Metadata

Metadata

Assignees

Labels

C:p2pComponent: P2P pkgT:bugType Bug (Confirmed)T:securityType: Security (specify priority)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions