Skip to content

Peer5/Prflxion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Prflxion

Introduction

Prflxion is a logical exploit of a sanitization bug in WebRTC that leaks the local IPv4 to the web application.
Until 2019, Using WebRTC candidates for this kind of leak was well known and used by vendors to accurately target users behind a NAT.
In 2019, following public pressure, the Chromium Team decided to implement an obfuscation method using the mDNS Protocol.
In short, mDNS uses the ip multicast feature to resolve local hostnames in a LAN. To make sure it does not cross routers, its TTL is limited to 1.
The exploit manipulates the generated candidates to circumvent the IP obfuscation by leveraging a common OS kernel feature.

The Vulnerability

The vulnerability lies within the code in the function Connection::MaybeUpdateLocalCandidate. This function is called whenever a STUN_BINDING_RESPONSE is received on a STUN connection. The function gets the XOR_MAPPED_ADDRESS sent by the STUN server - which is the client's IP address as seen by the server when receiving the bind request.
If the address is found within the current candidates, it changes the connection's local candidate to the one it found. Otherwise, it creates a new local candidate (one that has not been generated or sent by the STUN) and assumes it to be a prflx candidate.
The first problem is that the new candidate isn't Sanitized by the mDNS Obfuscation. This sanitization is done mainly in BasicPortAllocatorSession::OnCandidateReady when SignalCandidateReady is called.
But the function MaybeUpdateLocalCandidate does not signal this. Instead, it calls AddPrflxCandidate which adds it without sanitization to the candidate list.

The Exploit

At first sight there seems to be no trivial way to exploit this. i.e. to create an un-sanitized candidate with the local IPv4 address. To achieve that we would have to somehow represent the local IPv4 in a way that is on one hand different from candidate addresses created by the interface enumeration, and on the other hand needs to be supported by the network stack.
To aid us in this task comes IPv6.

4in6 encapsulation

As can be seen here, there and everywhere, when a client tries to connect in IPv4 to a server with dual-stack enabled that listens to an IPv6 (AF_INET6) defined socket on in6addr_any (::), a padding of the IPv4 address to an IPv6 address takes place in the kernel. this padded IPv6 address is returned from getaddrinfo() api (or recvfrom in our case) as the remote host.
for example, assume the following:

  • A Client with only IPv4 stack with ip 192.168.1.24.
  • A dual-stack enabled Server with IPv4 address 192.168.1.25 and IPv6 address 2002:a00:3::1006 that is listening on an AF_INET6, UDP (SOCK_DGRAM) socket. Bound to address :: and port 1337.

When the client connects to 192.168.1.25:1337, the Server's Kernel pads the IPv4 of the client because the server is expecting an IPv6 source IP when recvfrom is called. Thus, the Server will see the client as ::ffff:192.168.1.24. This is the address which will be returned as the XOR_MAPPED_ADDRESS in the following exploitation.

Exploitation

So, to exploit this we would need to initiate a STUN_BIND_REQUEST that will create a STUN_BIND_RESPONSE that has the 4in6 local IPv4 as XOR_MAPPED_ADDRESS. First, we don't define any STUN server so the STUN_BIND_REQUESTs will be sent directly to the other peer without translation. Fortunately, the WebRTC NetworkManagerBase class binds two UDP sockets - one on INADDR_ANY (0.0.0.0), and another on in6addr_any (::). These Sockets are used for the STUN negotiation.
So, when we create a RTCPeerConnection instance, we would expect that two mDNS candidates will be created (and obfuscated) - one for the IPv4 address and another for the IPv6 address (each with its own UDP port) These two candidates would have two different mDNS names (as per creation).
After the two candidates are collected, the exploit replaces the IPv6 candidate mDNS hostname (in JS) with the IPv4 candidate mDNS hostname. A second local connection is passed the malicious IPv6 candidate through RTCPeerConnection.addIceCandidate().
This results in a local mDNS name resolving of the IPv4 address, but the port that the second connection will try to connect with is the IPv6 defined socket, which means the address reported between the peers through STUN will be a 4in6 translated address.
This results in adding un-sanitized candidate to the WebRTC stats which are available via the RTCPeerConnection.getStats() method.

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages