Affects Version/s: 1.16.3
Fix Version/s: 1.16.4 Pre-release 2
Mojang Priority:Very Important
This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.
When first logging in, a client encrypts a 16-byte secret and token with the server's public key (PKCS #1 v1.5 padded). The server then decrypts the token and secret, and uses the secret to encrypt future communications with the client.
Unfortunately, the Minecraft server currently leaks information on failed decryption. If the given ciphertext decrypts to a message with incorrect padding, the server will return a generic "Missing argument" error. However, if a given ciphertext decrypts to a message with valid padding, the server will return "Wrong IV length: must be 16 bytes long", or an encrypted "sLoginSuccess". This allows an attacker to construct a padding oracle that can be used to decrypt eavesdropped communications between a client and the server.
This attack is a variant of Bleichenbacher's attack. Every protocol that uses RSA PKCS #1 v1.5 is at risk of exposing similar vulnerabilities.
An example attack scenario would be two clients (Alice and Eve) on the same local network connecting to a remote server (Bob). If Eve is able to capture the initial handshake sent by Alice, she can then make requests to Bob to break the encrypted secret, and then decrypt all communications shared between Alice and Bob. In this scenario Eve would also be able to inject her own data into the stream (e.g. commands or chat data) and impersonate Alice.
Attached is a PoC which demonstrates the attack. The script takes a wireshark packet capture containing the initial handshake as input. The script will then make requests to a local Minecraft server ('127.0.0.1:25565' by default) in order to break the shared secret, and then prints all decrypted chat packets. The script requires ~200,000 requests in order to break a secret, which usually takes about 5-10 minutes.
The main part of interest in the PoC is how "oracle" is defined. Preventing an attacker from constructing a reliable oracle stops this attack.
- Prevent information leaks during handshake (e.g. return generic error until connection is encrypted)
- Use RSA-OAEP, or preferably switch to elliptic curves for key exchange
Apologies if anything isn't clear. Please let me know if more information is needed.
Running the PoC:
1. Start minecraft client and server
2. Begin capture in wireshark
3. Connect to server (the PoC assumes you're using '127.0.0.1:25565')
4. Send some messages in the Minecraft chat
5. End wireshark capture
6. In wireshark: "Follow TCP stream" > "YAML" > "Export as..." > "pcap.yml"
7. "./poc.py pcap.yml" (will connect to '127.0.0.1:25565')