A vulnerability was discovered in Toxcore that allows one to learn the IP of a target user by only knowing their Tox Id and without being friends with the target user.

The Tox protocol is designed in such a way that only friends (contacts) which you have accepted friend requests of are able to learn your IP based on your Tox Id and no one else. Thus, being able to learn the IP of an owner of a Tox Id without them accepting a friend request is an undesired behavior.

This is a vulnerability in an implementation of the Tox protocol, a vulnerability in the Toxcore library, not in the Tox protocol itself.

The vulnerability affects both TokTok’s c-toxcore and irungentoo’s toxcore. The vulnerability affects only UDP mode of operation. TCP-only mode is not affected by the vulnerability.

TokTok’s c-toxcore has patched the vulnerability in version 0.2.2. irungentoo’s toxcore doesn’t have the vulnerability patched as of this moment and it’s unknown if it ever will, as it hasn’t been actively maintained for years. irungentoo’s toxcore was patched after this post was written.

The vulnerability was privately reported to us by Evgeny Kurnevsky on April 14th and publicly disclosed with our permission on April 15th, along with a patch fixing the vulnerability, made by Evgeny Kurnevsky. The vulnerability was found when Evgeny was working on tox-rs project – a Tox implementation in Rust.

We urge everyone to update to the latest TokTok c-toxcore as soon as possible. You can immediately mitigate the vulnerability for yourself by using TCP-only mode.

Due to the nature of the vulnerability, using Toxcore in which the vulnerability is patched is not enough to protect yourself. The way the patch works is that it can’t protect you from the vulnerability but it can and does protect other peers. So in order to be protected from the vulnerability, everyone should switch to using the patched Toxcore. The more people use the patched Toxcore, the less is the chance to be vulnerable. Note that this applies only to the UDP mode. If you use the TCP-only mode, you are fully protected as you are not affected by the vulnerability.

Details of the vulnerability

Here are the technical details of the vulnerability.

The vulnerability is caused by the Onion module of Toxcore erroneously allowing to onion-route any data, any Tox packets, without a restriction. By the Tox protocol specification, when Alice makes an onion-routed request to Bob and then Bob sends an onion-routed response back to Alice, the payload of the onion-routed response sent by Bob arrives to Alice as it is, stripped of any identification that it was ever onion-routed by the last onion hop, and is interpreted as a regular Tox packet by Alice. Alice has no way to distinguish onion and non-onion packets — she has no idea if the packet originated from the node it received the packet from, or if the packet was relayed on someone else’s behalf as part of an onion-routing. The way the onion routing is defined in the Tox specification and Toxcore erroneously not restricting the packets that can be onion-routed allows for some interesting interactions that weren’t meant to happen.

One of the packets that are onion-routed is the Announce Request packet. It’s used to announce ourselves to nodes close to our long term public key, the one that is a part of Tox Id, and the payload of that packet includes the long term public key itself. Let’s say Alice announces herself to a bunch of nodes, one of which happened to be Bob. (If Bob is malicious, he can purposefully keep re-generating his DHT keypair until his public key becomes close to Alice’s long term public key as to guarantee Alice announcing to him.) Based on the Announce Request packet, Bob now knows Alice’s long term public key and has a way to contact her back though the established onion path. If Bob is malicious, he could spawn many new DHT nodes, and send back to Alice a NAT Ping Request packet for one of its newly created nodes. The NAT Ping Request packet is used to ping a node on someone else’s behalf in order to circumvent the NAT. The NAT Ping Request is not meant to be onion routed. Alice will receive the NAT Ping Request packet and will diligently relay it to the Bob’s DHT node if it happened to be in Alice’s Close List of nodes, which will happen only if the DHT public key of Bob’s node is close to the DHT public key of Alice’s node. Bob doesn’t know Alice’s DHT public key, so Bob will have to make a guess. If Bob makes a bad guess and Alice doesn’t relay the packet to his node, Bob can re-try by sending the NAT Ping Request packet to Alice for a new DHT node, repeating this process as many times as he wants. Eventually Bob’s DHT node will have public key close to Alice’s DHT public key and end up in Alice’s Close Nodes list, making Alice relay the NAT Ping Request packet to it, unknowingly disclosing her IP to Bob. Now Bob knows both Alice’s long term public key and her IP without being friends with her.

What the patch does is make all nodes in the onion path check if the payload of the onion-routed response is a packet kind that shouldn’t be routed through the onion, and if so drop it. It also makes the node closest to the destination of the onion-routed request, which is the only node in the onion path of the onion-routed request that can see which packet kind is sent to the destination node, drop the onion-routed request if it has a packet kind that shouldn’t be routed through the onion. The latter doesn’t matter much as Alice can’t exploit Bob in any way by onion-routing him packets that are not supposed to be onion routed, it’s done more for data sanitization reasons.

Because there are only 3 nodes in the onion path, the source and destination excluded, the patch protects you as long as at least one of the three is using the patched Toxcore.

This vulnerability affects only the UDP mode. In TCP-only mode the Onion module restricts which Tox packets are onion-routed correctly, and the Tox protocol specification is written in such a way that nodes using TCP-only mode can distinguish between onion and non-onion packets. So all of the above applies only to the UDP mode.