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
fix(modtool): validate report payloads
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.modtool;
|
||||||
|
|
||||||
|
final class ModToolReportInputGuard {
|
||||||
|
static final int MAX_REPORT_MESSAGE_LENGTH = 1000;
|
||||||
|
static final int MAX_PRIVATE_CHAT_LOGS = 100;
|
||||||
|
static final int MAX_PRIVATE_CHAT_MESSAGE_LENGTH = 500;
|
||||||
|
|
||||||
|
private ModToolReportInputGuard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static String normalize(String value) {
|
||||||
|
return value == null ? "" : value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isValidReportMessage(String value) {
|
||||||
|
return value != null && !value.isEmpty() && value.length() <= MAX_REPORT_MESSAGE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isValidChatLogMessage(String value) {
|
||||||
|
return value != null && value.length() <= MAX_PRIVATE_CHAT_MESSAGE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isValidPrivateChatLogCount(int count) {
|
||||||
|
return count > 0 && count <= MAX_PRIVATE_CHAT_LOGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isPositiveId(int id) {
|
||||||
|
return id > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import java.util.ArrayList;
|
|||||||
public class ReportBullyEvent extends MessageHandler {
|
public class ReportBullyEvent extends MessageHandler {
|
||||||
@Override
|
@Override
|
||||||
public void handle() throws Exception {
|
public void handle() throws Exception {
|
||||||
if (this.client.getHabbo().getHabboStats().allowTalk()) {
|
if (!this.client.getHabbo().getHabboStats().allowTalk()) {
|
||||||
this.client.sendResponse(new HelperRequestDisabledComposer());
|
this.client.sendResponse(new HelperRequestDisabledComposer());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,9 @@ public class ReportBullyEvent extends MessageHandler {
|
|||||||
int userId = this.packet.readInt();
|
int userId = this.packet.readInt();
|
||||||
int roomId = this.packet.readInt();
|
int roomId = this.packet.readInt();
|
||||||
|
|
||||||
if (userId == this.client.getHabbo().getHabboInfo().getId()) {
|
if (!ModToolReportInputGuard.isPositiveId(userId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(roomId) ||
|
||||||
|
userId == this.client.getHabbo().getHabboInfo().getId()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-1
@@ -17,7 +17,15 @@ public class ReportCommentEvent extends MessageHandler {
|
|||||||
int threadId = this.packet.readInt();
|
int threadId = this.packet.readInt();
|
||||||
int commentId = this.packet.readInt();
|
int commentId = this.packet.readInt();
|
||||||
int topicId = this.packet.readInt();
|
int topicId = this.packet.readInt();
|
||||||
String message = this.packet.readString();
|
String message = ModToolReportInputGuard.normalize(this.packet.readString());
|
||||||
|
|
||||||
|
if (!ModToolReportInputGuard.isPositiveId(groupId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(threadId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(commentId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(topicId) ||
|
||||||
|
!ModToolReportInputGuard.isValidReportMessage(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CfhTopic topic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topicId);
|
CfhTopic topic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topicId);
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,26 @@ public class ReportEvent extends MessageHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = this.packet.readString();
|
String message = ModToolReportInputGuard.normalize(this.packet.readString());
|
||||||
int topic = this.packet.readInt();
|
int topic = this.packet.readInt();
|
||||||
int userId = this.packet.readInt();
|
int userId = this.packet.readInt();
|
||||||
int roomId = this.packet.readInt();
|
int roomId = this.packet.readInt();
|
||||||
this.packet.readInt();
|
this.packet.readInt();
|
||||||
|
|
||||||
|
if (!ModToolReportInputGuard.isValidReportMessage(message) ||
|
||||||
|
topic <= 0 ||
|
||||||
|
(userId != -1 && !ModToolReportInputGuard.isPositiveId(userId)) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(roomId) ||
|
||||||
|
userId == this.client.getHabbo().getHabboInfo().getId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CfhTopic cfhTopic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topic);
|
||||||
|
|
||||||
|
if (cfhTopic == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId);
|
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId);
|
||||||
List<ModToolIssue> issues = Emulator.getGameEnvironment().getModToolManager().openTicketsForHabbo(this.client.getHabbo());
|
List<ModToolIssue> issues = Emulator.getGameEnvironment().getModToolManager().openTicketsForHabbo(this.client.getHabbo());
|
||||||
if (!issues.isEmpty()) {
|
if (!issues.isEmpty()) {
|
||||||
@@ -35,8 +49,6 @@ public class ReportEvent extends MessageHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CfhTopic cfhTopic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topic);
|
|
||||||
|
|
||||||
if (userId != -1) {
|
if (userId != -1) {
|
||||||
Habbo reported = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId);
|
Habbo reported = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId);
|
||||||
|
|
||||||
@@ -117,4 +129,4 @@ public class ReportEvent extends MessageHandler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-3
@@ -21,12 +21,20 @@ public class ReportFriendPrivateChatEvent extends MessageHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = this.packet.readString();
|
String message = ModToolReportInputGuard.normalize(this.packet.readString());
|
||||||
int category = this.packet.readInt();
|
int category = this.packet.readInt();
|
||||||
int userId = this.packet.readInt();
|
int userId = this.packet.readInt();
|
||||||
int count = this.packet.readInt();
|
int count = this.packet.readInt();
|
||||||
ArrayList<ModToolChatLog> chatLogs = new ArrayList<>();
|
ArrayList<ModToolChatLog> chatLogs = new ArrayList<>();
|
||||||
|
|
||||||
|
if (!ModToolReportInputGuard.isValidReportMessage(message) ||
|
||||||
|
category <= 0 ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(userId) ||
|
||||||
|
userId == this.client.getHabbo().getHabboInfo().getId() ||
|
||||||
|
!ModToolReportInputGuard.isValidPrivateChatLogCount(count)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HabboInfo info;
|
HabboInfo info;
|
||||||
Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId);
|
Habbo target = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId);
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
@@ -37,11 +45,17 @@ public class ReportFriendPrivateChatEvent extends MessageHandler {
|
|||||||
|
|
||||||
if (info == null) return;
|
if (info == null) return;
|
||||||
|
|
||||||
for (int i = 0; i < Math.min(count, 100); i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
int chatUserId = this.packet.readInt();
|
int chatUserId = this.packet.readInt();
|
||||||
String username = this.packet.readInt() == info.getId() ? info.getUsername() : this.client.getHabbo().getHabboInfo().getUsername();
|
String username = this.packet.readInt() == info.getId() ? info.getUsername() : this.client.getHabbo().getHabboInfo().getUsername();
|
||||||
|
String chatMessage = ModToolReportInputGuard.normalize(this.packet.readString());
|
||||||
|
|
||||||
chatLogs.add(new ModToolChatLog(0, chatUserId, username, this.packet.readString()));
|
if (!ModToolReportInputGuard.isPositiveId(chatUserId) ||
|
||||||
|
!ModToolReportInputGuard.isValidChatLogMessage(chatMessage)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chatLogs.add(new ModToolChatLog(0, chatUserId, username, chatMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
ModToolIssue issue = new ModToolIssue(this.client.getHabbo().getHabboInfo().getId(), this.client.getHabbo().getHabboInfo().getUsername(), userId, info.getUsername(), 0, message, ModToolTicketType.IM);
|
ModToolIssue issue = new ModToolIssue(this.client.getHabbo().getHabboInfo().getId(), this.client.getHabbo().getHabboInfo().getUsername(), userId, info.getUsername(), 0, message, ModToolTicketType.IM);
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ public class ReportPhotoEvent extends MessageHandler {
|
|||||||
int topicId = this.packet.readInt();
|
int topicId = this.packet.readInt();
|
||||||
int itemId = this.packet.readInt();
|
int itemId = this.packet.readInt();
|
||||||
|
|
||||||
|
if (!ModToolReportInputGuard.isPositiveId(roomId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(topicId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(itemId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CfhTopic topic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topicId);
|
CfhTopic topic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topicId);
|
||||||
|
|
||||||
if (topic == null) return;
|
if (topic == null) return;
|
||||||
|
|||||||
+8
-1
@@ -16,7 +16,14 @@ public class ReportThreadEvent extends MessageHandler {
|
|||||||
int groupId = this.packet.readInt();
|
int groupId = this.packet.readInt();
|
||||||
int threadId = this.packet.readInt();
|
int threadId = this.packet.readInt();
|
||||||
int topicId = this.packet.readInt();
|
int topicId = this.packet.readInt();
|
||||||
String message = this.packet.readString();
|
String message = ModToolReportInputGuard.normalize(this.packet.readString());
|
||||||
|
|
||||||
|
if (!ModToolReportInputGuard.isPositiveId(groupId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(threadId) ||
|
||||||
|
!ModToolReportInputGuard.isPositiveId(topicId) ||
|
||||||
|
!ModToolReportInputGuard.isValidReportMessage(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CfhTopic topic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topicId);
|
CfhTopic topic = Emulator.getGameEnvironment().getModToolManager().getCfhTopic(topicId);
|
||||||
|
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.modtool;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class ModToolReportInputContractTest {
|
||||||
|
@Test
|
||||||
|
void reportHandlersNormalizeAndBoundFreeText() throws Exception {
|
||||||
|
Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool");
|
||||||
|
|
||||||
|
for (String handler : List.of(
|
||||||
|
"ReportEvent.java",
|
||||||
|
"ReportFriendPrivateChatEvent.java",
|
||||||
|
"ReportCommentEvent.java",
|
||||||
|
"ReportThreadEvent.java"
|
||||||
|
)) {
|
||||||
|
String source = Files.readString(base.resolve(handler));
|
||||||
|
|
||||||
|
assertTrue(source.contains("ModToolReportInputGuard.normalize"),
|
||||||
|
handler + " must normalize report text before persistence or staff broadcast");
|
||||||
|
assertTrue(source.contains("ModToolReportInputGuard.isValidReportMessage"),
|
||||||
|
handler + " must reject empty or oversized report text");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reportHandlersRejectInvalidIdsAndCounts() throws Exception {
|
||||||
|
Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool");
|
||||||
|
|
||||||
|
for (String handler : List.of(
|
||||||
|
"ReportEvent.java",
|
||||||
|
"ReportFriendPrivateChatEvent.java",
|
||||||
|
"ReportCommentEvent.java",
|
||||||
|
"ReportThreadEvent.java",
|
||||||
|
"ReportBullyEvent.java",
|
||||||
|
"ReportPhotoEvent.java"
|
||||||
|
)) {
|
||||||
|
String source = Files.readString(base.resolve(handler));
|
||||||
|
|
||||||
|
assertTrue(source.contains("ModToolReportInputGuard.isPositiveId"),
|
||||||
|
handler + " must reject zero or negative ids supplied by the client");
|
||||||
|
}
|
||||||
|
|
||||||
|
String privateChat = Files.readString(base.resolve("ReportFriendPrivateChatEvent.java"));
|
||||||
|
assertTrue(privateChat.contains("ModToolReportInputGuard.isValidPrivateChatLogCount(count)"),
|
||||||
|
"private chat reports must reject negative or oversized client-provided chatlog counts");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reportEventValidatesTopicBeforeUsingReply() throws Exception {
|
||||||
|
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool/ReportEvent.java"));
|
||||||
|
|
||||||
|
assertTrue(source.indexOf("if (cfhTopic == null)") < source.indexOf("cfhTopic.reply"),
|
||||||
|
"ReportEvent must reject unknown topics before dereferencing the reply text");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bullyReportUsesSameMutedUserGateAsNormalReports() throws Exception {
|
||||||
|
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool/ReportBullyEvent.java"));
|
||||||
|
|
||||||
|
assertTrue(source.contains("if (!this.client.getHabbo().getHabboStats().allowTalk())"),
|
||||||
|
"bully reports must reject muted users instead of rejecting users who can talk");
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
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 ModToolReportInputGuardTest {
|
||||||
|
@Test
|
||||||
|
void normalizesNullableMessages() {
|
||||||
|
assertEquals("", ModToolReportInputGuard.normalize(null));
|
||||||
|
assertEquals("report", ModToolReportInputGuard.normalize(" report "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reportMessagesMustBeNonEmptyAndBounded() {
|
||||||
|
assertFalse(ModToolReportInputGuard.isValidReportMessage(""));
|
||||||
|
assertFalse(ModToolReportInputGuard.isValidReportMessage(null));
|
||||||
|
assertTrue(ModToolReportInputGuard.isValidReportMessage("a".repeat(ModToolReportInputGuard.MAX_REPORT_MESSAGE_LENGTH)));
|
||||||
|
assertFalse(ModToolReportInputGuard.isValidReportMessage("a".repeat(ModToolReportInputGuard.MAX_REPORT_MESSAGE_LENGTH + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void privateChatLogCountsAreBounded() {
|
||||||
|
assertFalse(ModToolReportInputGuard.isValidPrivateChatLogCount(0));
|
||||||
|
assertTrue(ModToolReportInputGuard.isValidPrivateChatLogCount(ModToolReportInputGuard.MAX_PRIVATE_CHAT_LOGS));
|
||||||
|
assertFalse(ModToolReportInputGuard.isValidPrivateChatLogCount(ModToolReportInputGuard.MAX_PRIVATE_CHAT_LOGS + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void idsMustBePositive() {
|
||||||
|
assertFalse(ModToolReportInputGuard.isPositiveId(0));
|
||||||
|
assertFalse(ModToolReportInputGuard.isPositiveId(-1));
|
||||||
|
assertTrue(ModToolReportInputGuard.isPositiveId(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user