diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolAlertEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolAlertEvent.java index 09b4ebb3..c2b6820f 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolAlertEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolAlertEvent.java @@ -11,10 +11,17 @@ public class ModToolAlertEvent extends MessageHandler { @Override public void handle() throws Exception { if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { - Habbo alertedUser = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.packet.readInt()); + int userId = this.packet.readInt(); + String message = ModToolInputGuard.normalize(this.packet.readString()); + + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + + Habbo alertedUser = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); if (alertedUser != null) - Emulator.getGameEnvironment().getModToolManager().alert(this.client.getHabbo(), alertedUser, this.packet.readString(), SupportUserAlertedReason.ALERT); + Emulator.getGameEnvironment().getModToolManager().alert(this.client.getHabbo(), alertedUser, message, SupportUserAlertedReason.ALERT); } else { ScripterManager.scripterDetected(this.client, Emulator.getTexts().getValue("scripter.warning.modtools.kick").replace("%username%", this.client.getHabbo().getHabboInfo().getUsername())); } diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolInputGuard.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolInputGuard.java new file mode 100644 index 00000000..f401a99a --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolInputGuard.java @@ -0,0 +1,16 @@ +package com.eu.habbo.messages.incoming.modtool; + +final class ModToolInputGuard { + static final int MAX_MESSAGE_LENGTH = 1000; + + private ModToolInputGuard() { + } + + static String normalize(String value) { + return value == null ? "" : value.trim(); + } + + static boolean isSafeMessage(String value) { + return value != null && !value.isEmpty() && value.length() <= MAX_MESSAGE_LENGTH; + } +} diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolKickEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolKickEvent.java index 6491a4bf..da01445a 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolKickEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolKickEvent.java @@ -18,6 +18,13 @@ public class ModToolKickEvent extends MessageHandler { return; } - Emulator.getGameEnvironment().getModToolManager().kick(this.client.getHabbo(), Emulator.getGameEnvironment().getHabboManager().getHabbo(this.packet.readInt()), this.packet.readString()); + int userId = this.packet.readInt(); + String message = ModToolInputGuard.normalize(this.packet.readString()); + + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + + Emulator.getGameEnvironment().getModToolManager().kick(this.client.getHabbo(), Emulator.getGameEnvironment().getHabboManager().getHabbo(userId), message); } } diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolRoomAlertEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolRoomAlertEvent.java index 99f0bc0a..db84edf3 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolRoomAlertEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolRoomAlertEvent.java @@ -11,10 +11,15 @@ public class ModToolRoomAlertEvent extends MessageHandler { public void handle() throws Exception { if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { this.packet.readInt(); + String message = ModToolInputGuard.normalize(this.packet.readString()); + + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom(); if (room != null) { - room.alert(this.packet.readString()); + room.alert(message); } } else { ScripterManager.scripterDetected(this.client, Emulator.getTexts().getValue("scripter.warning.roomalert").replace("%username%", this.client.getHabbo().getHabboInfo().getUsername())); diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionAlertEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionAlertEvent.java index cb609001..c37f1f52 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionAlertEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionAlertEvent.java @@ -21,9 +21,13 @@ public class ModToolSanctionAlertEvent extends MessageHandler { @Override public void handle() throws Exception { int userId = this.packet.readInt(); - String message = this.packet.readString(); + String message = ModToolInputGuard.normalize(this.packet.readString()); int cfhTopic = this.packet.readInt(); + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionBanEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionBanEvent.java index 5a2c8afa..d23f943a 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionBanEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionBanEvent.java @@ -30,13 +30,17 @@ public class ModToolSanctionBanEvent extends MessageHandler { @Override public void handle() throws Exception { int userId = this.packet.readInt(); - String message = this.packet.readString(); + String message = ModToolInputGuard.normalize(this.packet.readString()); int cfhTopic = this.packet.readInt(); int banType = this.packet.readInt(); this.packet.readBoolean(); int duration = 0; + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + switch (banType) { case BAN_18_HOURS: duration = 18 * 60 * 60; @@ -79,4 +83,4 @@ public class ModToolSanctionBanEvent extends MessageHandler { ScripterManager.scripterDetected(this.client, Emulator.getTexts().getValue("scripter.warning.modtools.ban").replace("%username%", this.client.getHabbo().getHabboInfo().getUsername())); } } -} \ No newline at end of file +} diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionMuteEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionMuteEvent.java index 16a2bbdd..e5f91ab2 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionMuteEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionMuteEvent.java @@ -23,9 +23,13 @@ public class ModToolSanctionMuteEvent extends MessageHandler { @Override public void handle() throws Exception { int userId = this.packet.readInt(); - String message = this.packet.readString(); + String message = ModToolInputGuard.normalize(this.packet.readString()); int cfhTopic = this.packet.readInt(); + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionTradeLockEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionTradeLockEvent.java index 9f666868..b49134f6 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionTradeLockEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolSanctionTradeLockEvent.java @@ -21,10 +21,14 @@ public class ModToolSanctionTradeLockEvent extends MessageHandler { @Override public void handle() throws Exception { int userId = this.packet.readInt(); - String message = this.packet.readString(); + String message = ModToolInputGuard.normalize(this.packet.readString()); int duration = this.packet.readInt(); int cfhTopic = this.packet.readInt(); + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolWarnEvent.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolWarnEvent.java index a8dae64f..06c118b2 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolWarnEvent.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/modtool/ModToolWarnEvent.java @@ -16,10 +16,17 @@ public class ModToolWarnEvent extends MessageHandler { @Override public void handle() throws Exception { if (this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { - Habbo alertedUser = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.packet.readInt()); + int userId = this.packet.readInt(); + String message = ModToolInputGuard.normalize(this.packet.readString()); + + if (!ModToolInputGuard.isSafeMessage(message)) { + return; + } + + Habbo alertedUser = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); if (alertedUser != null) - Emulator.getGameEnvironment().getModToolManager().alert(this.client.getHabbo(), alertedUser, this.packet.readString(), SupportUserAlertedReason.CAUTION); + Emulator.getGameEnvironment().getModToolManager().alert(this.client.getHabbo(), alertedUser, message, SupportUserAlertedReason.CAUTION); } else { ScripterManager.scripterDetected(this.client, Emulator.getTexts().getValue("scripter.warning.modtools.kick").replace("%username%", this.client.getHabbo().getHabboInfo().getUsername())); } diff --git a/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolInputGuardTest.java b/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolInputGuardTest.java new file mode 100644 index 00000000..214d2087 --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolInputGuardTest.java @@ -0,0 +1,23 @@ +package com.eu.habbo.messages.incoming.modtool; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ModToolInputGuardTest { + @Test + void normalizesNullableMessages() { + assertEquals("", ModToolInputGuard.normalize(null)); + assertEquals("warn", ModToolInputGuard.normalize(" warn ")); + } + + @Test + void staffMessagesMustBeNonEmptyAndBounded() { + assertFalse(ModToolInputGuard.isSafeMessage(null)); + assertFalse(ModToolInputGuard.isSafeMessage("")); + assertTrue(ModToolInputGuard.isSafeMessage("a".repeat(ModToolInputGuard.MAX_MESSAGE_LENGTH))); + assertFalse(ModToolInputGuard.isSafeMessage("a".repeat(ModToolInputGuard.MAX_MESSAGE_LENGTH + 1))); + } +} diff --git a/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolPermissionContractTest.java b/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolPermissionContractTest.java index 9ab0ff8d..ba03fc67 100644 --- a/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolPermissionContractTest.java +++ b/Emulator/src/test/java/com/eu/habbo/messages/incoming/modtool/ModToolPermissionContractTest.java @@ -86,4 +86,27 @@ class ModToolPermissionContractTest { assertTrue(defaultSanction.contains("if (issue == null)"), "default sanctions must tolerate stale or missing ticket ids"); } + + @Test + void staffSuppliedModToolMessagesAreBounded() throws Exception { + Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool"); + + for (String handler : List.of( + "ModToolAlertEvent.java", + "ModToolWarnEvent.java", + "ModToolKickEvent.java", + "ModToolRoomAlertEvent.java", + "ModToolSanctionAlertEvent.java", + "ModToolSanctionBanEvent.java", + "ModToolSanctionMuteEvent.java", + "ModToolSanctionTradeLockEvent.java" + )) { + String source = Files.readString(base.resolve(handler)); + + assertTrue(source.contains("ModToolInputGuard.normalize"), + handler + " must normalize staff-supplied text before use"); + assertTrue(source.contains("ModToolInputGuard.isSafeMessage"), + handler + " must reject empty or oversized staff-supplied text"); + } + } }