You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 07:26:18 +00:00
Merge branch 'dev' into fix/nitro-secure-api-safety
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
package com.eu.habbo.messages.incoming.handshake;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class SecureLoginGuardContractTest {
|
||||
|
||||
private static String source() throws Exception {
|
||||
return Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/handshake/SecureLoginEvent.java"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void websocketSsoTicketIsLengthBoundedBeforeDatabaseLookup() throws Exception {
|
||||
String source = source();
|
||||
|
||||
int maxConstant = source.indexOf("MAX_SSO_TICKET_LENGTH = 128");
|
||||
int guard = source.indexOf("sso.isEmpty() || sso.length() > MAX_SSO_TICKET_LENGTH");
|
||||
int lookup = source.indexOf("SELECT id FROM users WHERE auth_ticket = ?");
|
||||
|
||||
assertTrue(maxConstant > -1, "Secure login should define the same SSO length cap used by HTTP auth");
|
||||
assertTrue(guard > -1, "Secure login must reject missing or oversized SSO tickets");
|
||||
assertTrue(guard < lookup, "SSO length must be validated before database lookup");
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.eu.habbo.networking.gameserver.auth;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class AuthTokenGuardContractTest {
|
||||
|
||||
@Test
|
||||
void accessTokenRejectsOversizedTokensBeforeSplitAndDecode() throws Exception {
|
||||
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/networking/gameserver/auth/AccessTokenService.java"));
|
||||
|
||||
int maxConstant = source.indexOf("MAX_TOKEN_CHARS = 2048");
|
||||
int lengthGuard = source.indexOf("token.length() > MAX_TOKEN_CHARS");
|
||||
int split = source.indexOf("token.split");
|
||||
int decode = source.indexOf("URL_DEC.decode");
|
||||
|
||||
assertTrue(maxConstant > -1, "Access tokens should have a bounded serialized size");
|
||||
assertTrue(lengthGuard > -1, "Access token verification must reject oversized tokens");
|
||||
assertTrue(lengthGuard < split, "Access token length guard must run before split");
|
||||
assertTrue(lengthGuard < decode, "Access token length guard must run before Base64 decode");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rememberTokenRejectsOversizedTokensBeforeSplitAndDecode() throws Exception {
|
||||
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/networking/gameserver/auth/RememberJwtService.java"));
|
||||
|
||||
int maxConstant = source.indexOf("MAX_TOKEN_CHARS = 2048");
|
||||
int lengthGuard = source.indexOf("jwt.length() > MAX_TOKEN_CHARS");
|
||||
int split = source.indexOf("jwt.split");
|
||||
int decode = source.indexOf("URL_DEC.decode");
|
||||
|
||||
assertTrue(maxConstant > -1, "Remember tokens should have a bounded serialized size");
|
||||
assertTrue(lengthGuard > -1, "Remember token verification must reject oversized tokens");
|
||||
assertTrue(lengthGuard < split, "Remember token length guard must run before split");
|
||||
assertTrue(lengthGuard < decode, "Remember token length guard must run before Base64 decode");
|
||||
}
|
||||
}
|
||||
+36
@@ -50,6 +50,30 @@ class RCONServerHandlerContractTest {
|
||||
assertTrue(registerIndex < serverIndex, "RCON rate limit defaults must be registered before RCONServer is constructed");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rconPayloadSizeIsBoundedBeforeBufferCopy() throws Exception {
|
||||
String handler = handlerSource();
|
||||
String emulator = emulatorSource();
|
||||
|
||||
int readableBytes = handler.indexOf("int readableBytes = data.readableBytes()");
|
||||
int maxPayload = handler.indexOf("int maxPayloadBytes = maxPayloadBytes()", readableBytes);
|
||||
int oversizedGuard = handler.indexOf("readableBytes > maxPayloadBytes", maxPayload);
|
||||
int byteArray = handler.indexOf("new byte[readableBytes]", readableBytes);
|
||||
|
||||
assertTrue(handler.contains("DEFAULT_MAX_PAYLOAD_BYTES = 64 * 1024"),
|
||||
"RCON handler should have a conservative default payload cap");
|
||||
assertTrue(handler.contains("rcon.max_payload_bytes"),
|
||||
"RCON max payload should be configurable");
|
||||
assertTrue(readableBytes > -1, "RCON handler must read ByteBuf size before allocation");
|
||||
assertTrue(maxPayload > readableBytes, "RCON handler must resolve max payload before allocation");
|
||||
assertTrue(oversizedGuard > maxPayload, "RCON handler must reject oversized payloads");
|
||||
assertTrue(oversizedGuard < byteArray, "Oversized RCON payloads must be rejected before byte array allocation");
|
||||
assertTrue(handler.contains("PAYLOAD_TOO_LARGE"),
|
||||
"RCON callers need a deterministic response for oversized payloads");
|
||||
assertTrue(emulator.contains("register(\"rcon.max_payload_bytes\", \"65536\")"),
|
||||
"RCON max payload default must be registered before startup");
|
||||
}
|
||||
|
||||
@Test
|
||||
void inboundByteBufIsReleasedFromFinallyBlock() throws Exception {
|
||||
String source = handlerSource();
|
||||
@@ -59,4 +83,16 @@ class RCONServerHandlerContractTest {
|
||||
assertTrue(finallyIndex >= 0, "RCON channelRead must release inbound ByteBufs from a finally block");
|
||||
assertTrue(releaseIndex > finallyIndex, "RCON channelRead must release the inbound ByteBuf after finally starts");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rconWhitelistUsesSocketAddressInsteadOfStringSplitting() throws Exception {
|
||||
String source = handlerSource();
|
||||
|
||||
assertTrue(source.contains("InetSocketAddress"),
|
||||
"RCON whitelist should resolve socket addresses instead of parsing remoteAddress.toString()");
|
||||
assertTrue(source.contains("getHostAddress()"),
|
||||
"RCON whitelist should compare the resolved host address");
|
||||
assertTrue(!source.contains(".toString().split(\":\")"),
|
||||
"RCON whitelist must not split host:port strings because that breaks IPv6 addresses");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user