geforkt von Mirrors/Velocity
Add upfront size checks for some packets.
This is simply a further protection against certain attacks which send malformed packets to the proxy.
Dieser Commit ist enthalten in:
Ursprung
959e75d16d
Commit
5ceac16a82
@ -11,4 +11,12 @@ public interface MinecraftPacket {
|
|||||||
void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion);
|
void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion);
|
||||||
|
|
||||||
boolean handle(MinecraftSessionHandler handler);
|
boolean handle(MinecraftSessionHandler handler);
|
||||||
|
|
||||||
|
default int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int expectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
ctx.fireChannelRead(buf);
|
ctx.fireChannelRead(buf);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
doLengthSanityChecks(buf, packet);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
packet.decode(buf, direction, registry.version);
|
packet.decode(buf, direction, registry.version);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -65,7 +67,7 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buf.isReadable()) {
|
if (buf.isReadable()) {
|
||||||
throw handleNotReadEnough(packet, packetId);
|
throw handleOverflow(packet, buf.readerIndex(), buf.writerIndex());
|
||||||
}
|
}
|
||||||
ctx.fireChannelRead(packet);
|
ctx.fireChannelRead(packet);
|
||||||
} finally {
|
} finally {
|
||||||
@ -74,10 +76,30 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Exception handleNotReadEnough(MinecraftPacket packet, int packetId) {
|
private void doLengthSanityChecks(ByteBuf buf, MinecraftPacket packet) throws Exception {
|
||||||
|
int expectedMinLen = packet.expectedMinLength(buf, direction, registry.version);
|
||||||
|
int expectedMaxLen = packet.expectedMaxLength(buf, direction, registry.version);
|
||||||
|
if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) {
|
||||||
|
throw handleOverflow(packet, expectedMaxLen, buf.readableBytes());
|
||||||
|
}
|
||||||
|
if (buf.readableBytes() < expectedMinLen) {
|
||||||
|
throw handleUnderflow(packet, expectedMaxLen, buf.readableBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception handleOverflow(MinecraftPacket packet, int expected, int actual) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
return new CorruptedFrameException("Did not read full packet for " + packet.getClass() + " "
|
return new CorruptedFrameException("Packet sent for " + packet.getClass() + " was too "
|
||||||
+ getExtraConnectionDetail(packetId));
|
+ "big (expected " + expected + " bytes, got " + actual + " bytes)");
|
||||||
|
} else {
|
||||||
|
return DECODE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception handleUnderflow(MinecraftPacket packet, int expected, int actual) {
|
||||||
|
if (DEBUG) {
|
||||||
|
return new CorruptedFrameException("Packet sent for " + packet.getClass() + " was too "
|
||||||
|
+ "small (expected " + expected + " bytes, got " + actual + " bytes)");
|
||||||
} else {
|
} else {
|
||||||
return DECODE_FAILED;
|
return DECODE_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ public class EncryptionResponse implements MinecraftPacket {
|
|||||||
@Override
|
@Override
|
||||||
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
|
||||||
this.sharedSecret = ProtocolUtils.readByteArray(buf, 256);
|
this.sharedSecret = ProtocolUtils.readByteArray(buf, 128);
|
||||||
this.verifyToken = ProtocolUtils.readByteArray(buf, 128);
|
this.verifyToken = ProtocolUtils.readByteArray(buf, 128);
|
||||||
} else {
|
} else {
|
||||||
this.sharedSecret = ProtocolUtils.readByteArray17(buf);
|
this.sharedSecret = ProtocolUtils.readByteArray17(buf);
|
||||||
@ -56,4 +57,16 @@ public class EncryptionResponse implements MinecraftPacket {
|
|||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
// It turns out these come out to the same length, whether we're talking >=1.8 or not.
|
||||||
|
// The length prefix always winds up being 2 bytes.
|
||||||
|
return 260;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return expectedMaxLength(buf, direction, version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import com.velocitypowered.proxy.util.except.QuietDecoderException;
|
import com.velocitypowered.proxy.util.except.QuietDecoderException;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -52,6 +53,13 @@ public class ServerLogin implements MinecraftPacket {
|
|||||||
ProtocolUtils.writeString(buf, username);
|
ProtocolUtils.writeString(buf, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
// Accommodate the rare (but likely malicious) use of UTF-8 usernames, since it is technically
|
||||||
|
// legal on the protocol level.
|
||||||
|
return 1 + (16 * 4);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
|
@ -4,6 +4,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
public class StatusPing implements MinecraftPacket {
|
public class StatusPing implements MinecraftPacket {
|
||||||
@ -24,4 +25,14 @@ public class StatusPing implements MinecraftPacket {
|
|||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
public class StatusRequest implements MinecraftPacket {
|
public class StatusRequest implements MinecraftPacket {
|
||||||
@ -33,4 +34,9 @@ public class StatusRequest implements MinecraftPacket {
|
|||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren