fix(rooms): scope self moderation to current room

Reject client-supplied room ids for self-moderation packets unless they match the caller's current room. This prevents users with saved rights or ownership in another room from muting, banning, or unbanning users remotely via crafted packets.

RoomUserBanEvent now also ignores invalid ban type values instead of letting valueOf throw through the message handler.

Add a contract test covering ban, mute, and unban current-room scoping.
This commit is contained in:
simoleo89
2026-06-13 17:20:01 +02:00
parent 87e1ef94f7
commit eb41e3afb9
4 changed files with 55 additions and 17 deletions
@@ -2,6 +2,7 @@ package com.eu.habbo.messages.incoming.rooms.users;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.rooms.RoomManager;
import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.messages.incoming.MessageHandler;
public class RoomUserBanEvent extends MessageHandler {
@@ -11,6 +12,18 @@ public class RoomUserBanEvent extends MessageHandler {
int roomId = this.packet.readInt();
String banName = this.packet.readString();
Emulator.getGameEnvironment().getRoomManager().banUserFromRoom(this.client.getHabbo(), userId, roomId, RoomManager.RoomBanTypes.valueOf(banName));
Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom();
if (room == null || room.getId() != roomId) {
return;
}
RoomManager.RoomBanTypes banType;
try {
banType = RoomManager.RoomBanTypes.valueOf(banName);
} catch (IllegalArgumentException e) {
return;
}
Emulator.getGameEnvironment().getRoomManager().banUserFromRoom(this.client.getHabbo(), userId, roomId, banType);
}
}
}
@@ -15,17 +15,18 @@ public class RoomUserMuteEvent extends MessageHandler {
int roomId = this.packet.readInt();
int minutes = this.packet.readInt();
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId);
Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom();
if (room == null || room.getId() != roomId) {
return;
}
if (room != null) {
if (room.hasRights(this.client.getHabbo()) || this.client.getHabbo().hasPermission("cmd_mute") || this.client.getHabbo().hasPermission(Permission.ACC_AMBASSADOR)) {
Habbo habbo = room.getHabbo(userId);
if (room.hasRights(this.client.getHabbo()) || this.client.getHabbo().hasPermission("cmd_mute") || this.client.getHabbo().hasPermission(Permission.ACC_AMBASSADOR)) {
Habbo habbo = room.getHabbo(userId);
if (habbo != null) {
room.muteHabbo(habbo, minutes);
habbo.getClient().sendResponse(new MutedWhisperComposer(minutes * 60));
AchievementManager.progressAchievement(this.client.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("SelfModMuteSeen"));
}
if (habbo != null) {
room.muteHabbo(habbo, minutes);
habbo.getClient().sendResponse(new MutedWhisperComposer(minutes * 60));
AchievementManager.progressAchievement(this.client.getHabbo(), Emulator.getGameEnvironment().getAchievementManager().getAchievement("SelfModMuteSeen"));
}
}
}
@@ -10,13 +10,13 @@ public class UnbanRoomUserEvent extends MessageHandler {
int userId = this.packet.readInt();
int roomId = this.packet.readInt();
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId);
if (room != null) {
if (room.isOwner(this.client.getHabbo())) {
room.unbanHabbo(userId);
}
Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom();
if (room == null || room.getId() != roomId) {
return;
}
if (room.isOwner(this.client.getHabbo())) {
room.unbanHabbo(userId);
}
}
}
@@ -0,0 +1,24 @@
package com.eu.habbo.messages.incoming.rooms.users;
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 RoomModerationScopeContractTest {
@Test
void roomUserBanAndMuteAreScopedToCurrentRoom() throws Exception {
Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/rooms/users");
for (String handler : new String[]{"RoomUserBanEvent.java", "RoomUserMuteEvent.java", "UnbanRoomUserEvent.java"}) {
String source = Files.readString(base.resolve(handler));
assertTrue(source.contains("getCurrentRoom()"),
handler + " must authorize room moderation against the user's current room");
assertTrue(source.contains("room.getId() != roomId"),
handler + " must reject client-supplied room ids that do not match the current room");
}
}
}