The world’s most popular torrent client, uTorrent, contained a security vulnerability — later to be called CVE-2020-8437— that could be exploited by a remote attacker to crash and corrupt any uTorrent instance connected to the internet.As white-hat hackers, my friend (who wishes to remain anonymous) and I reported this vulnerability as soon as we found it and it was quickly fixed. Now, after ample time has been given for users to update, it’s safe to disclose an overview of the vulnerability and how to exploit it.
Torrent Protocol - What You Need To Know
Torrent downloads utilize simultaneous connections to multiple peers (other people downloading the same file), creating a decentralized download network that benefits the collective peer group. Each peer can upload and download data to and from any other peer, eliminating any single point of failure or bandwidth bottleneck, resulting in a faster and more stable download for all peers.
Peers communicate with each other using the BitTorrent protocol, which is initiated with a handshake. We’re going to focus on this handshake and the packet following it because that’s all that’s needed for exploiting the CVE-2020-8437 uTorrent vulnerability. Surprisingly convenient. 😊
BitTorrent Handshake
The handshake packet is the first packet the initiating peer sends to another peer. It has 5 fields in a strictly structured format:
Handshake Packet Format
- Name Length - 1 byte unsigned int - The length of the string that follows.
- Protocol Name - variable length string - The protocol the initiating peer supports. This field is for future compatibility, but is set to “BitTorrent protocol” in all major implementations.
- Reserved Bytes - 8 byte bitfield - Each bit represents a protocol extension (functionality) that was not part of the original BitTorrent specification. Modern torrent clients utilize this field to communicate their advanced capabilities, which are then used for an optimized download. Today, the grand majority of torrent clients support the “Extension Protocol” extension (confusing name, I know), the 20th bit in this bit field, that provides a foundation for exchanging information about other extensions. Yes, you understood that correctly: there is an extension bit that allows for even more extensions. I wonder what such a complicated protocol can lead to 😉.
- Info Hash - 20 byte SHA1 - Used to identify the torrent the initiating peer wants to download, this is the hash of all the information needed to download the torrent (torrent name, hashes of file sections, file section size, file section count, etc…).
- Peer ID - 20 byte buffer - A self-designated random ID the initiating peer gives itself.
After a peer receives a handshake packet, it replies with its own handshake packet in the exact same format.
If both peers set the Extension Protocol bit in the Reserved Bytes field, the peers then exchange further information about extensions, using an “Extended” message handshake.
BitTorrent Extended Message Handshake
The Extended Message Handshake is used by peers to share the exact additional extensions they support and other supplemental information. Unlike the BitTorrent handshake packet we previously examined, which was (practically) statically sized, the Extended Message’s Handshake packet can dynamically grow, allowing the packet to transport a multitude of extension data.
Extended Message Handshake Packet Format
- Length - 4 bytes unsigned int - the length of the entire message that follows
- BitTorrent Message Type - 1 byte - The BitTorrent message ID of this packet. This is set to 20 (0x14) for Extended Messages
- BitTorrent Extended Message Type - 1 byte - The Extended Message ID of this extended message. This is set to 0 for an extension exchange.
- M - dynamically sized - a bencoded dictionary of the supplemental extensions supported.
Bencoded Dictionaries
The M field is a bencoded dictionary, which is a format similar to a python dictionary: string-type keys are associated with values. However, in contrast to python dictionaries, bencoded dictionaries include the length of each string before its value, and “d” and “e” are used instead of “{“ and “}” respectively. Below is an example of a python dictionary and its corresponding bencoded dictionary encoding (newlines and spaces inserted in both formats for clarity).
Additionally, just as a python dictionary can contain a separate dictionary inside itself (and another dictionary inside that one, etc…), so too can a benencoded dictionary.
The CVE-2020-8437 Vulnerability
The CVE-2020-8437 vulnerability is in how uTorrent parses bencoded dictionaries - specifically, nested dictionaries. Before the patch (uTorrent 3.5.5 and earlier), uTorrent would use an integer (32 bits) as a bit field to keep track of which layer in the bencoded dictionary it was currently parsing. For example, when uTorrent would parse the first layer, the bit field would hold ‘00000000 00000000 00000000 00000001’, and when uTorrent would parse the second layer, the bit field would hold ‘00000000 00000000 00000000 00000011’.
“But what happens if uTorrent parses a bencoded dictionary with more than 32 layers of nested dictionaries?”, my friend and I curiously asked one Thursday night. So we quickly created such a dictionary and fed it into uTorrent’s bencoding dictionary parser. The result:
Awesome Possum! uTorrent crashed! Further inspection of the crash revealed its source: a null pointer dereference.
Exploiting CVE-2020-8437
There are two easy exploit vectors for CVE-2020-8437: The first is a remote peer sending an Extended Message packet with a malicious bencoded dictionary, and the second is a .torrent file that contains a malicious bencoded dictionary.
Remote Peer Exploit
As described earlier, when two peers that support Extended Messages start communicating with each other, they each send a packet enumerating the various extensions they support. That information about supported extensions is sent as a bencoded dictionary, and since that bencoded dictionary gets parsed by the client, if that dictionary is malicious (having more than 32 nested dictionaries layers), it will trigger CVE-2020-8437. 😊
Torrent File Exploit
.torrent files encapsulate the most basic information a client needs to start downloading torrents. These files are openly and commonly shared on torrent websites, downloaded, and then opened by torrent clients, effectively making these files a possible vehicle for triggering vulnerabilities in those torrent clients. Let me take you on a behind-the-scenes-sneak-peek-never-before-seen-on-live-tv look at the internals of a .torrent file, exposing how simple it is to use it to trigger CVE-2020-8437: a .torrent file is simply a bencoded dictionary saved as a file. So to exploit CVE-2020-8437 from a .torrent file, you just need to save a malicious bencoded dictionary to a file and give that file the .torrent extension. Check out my .torrent file exploit.
Proof of concept video of crashing uTorrent with the malicious .torrent file
Thank you Ben for helping me edit this blog post! 😄
Follow me on twitter for the latest on my security research adventures