diff --git a/CHANGELOG.md b/CHANGELOG.md index 85d31e64..9a3902b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Correct rejection message in LandGolfBallInCupHandler to output the proper expected player id. (@drunderscore) * Clarified the error mesage that the console is presented if a rate-limit is reached over REST to indicate that "tokens" actually refers to rate-limit tokens, and not auth tokens, and added a hint as to what config setting determines this. (@hakusaro, @patsore) * Fixed an issue where, when the console was redirected, input was disabled and commands didn't work, in TSAPI. You can now pass `-disable-commands` to disable the input thread, but by default, it will be enabled. Fixes [#1450](https://github.com/Pryaxis/TShock/issues/1450). (@DeathCradle, @QuiCM) +* Properly sanitize packet tile coordinates that coulbe used to DoS attack a server. This was assigned [GHSA-jq4j-v8pr-jv7j](https://github.com/Pryaxis/TShock/security/advisories/GHSA-jq4j-v8pr-jv7j). (@drunderscore) ## TShock 4.5.4 * Fixed ridiculous typo in `GetDataHandlers` which caused TShock to read the wrong field in the packet for `usingBiomeTorches`. (@hakusaro, @Arthri) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 42cc6cd1..60737a7f 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -260,6 +260,13 @@ namespace TShockAPI try { + if (!TShock.Utils.TilePlacementValid(tileX, tileY)) + { + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tile placement valid) {0} {1} {2}", args.Player.Name, action, editData); + args.Handled = true; + return; + } + if (editData < 0 || ((action == EditAction.PlaceTile || action == EditAction.ReplaceTile) && editData >= Main.maxTileSets) || ((action == EditAction.PlaceWall || action == EditAction.ReplaceWall) && editData >= Main.maxWallTypes)) @@ -270,14 +277,6 @@ namespace TShockAPI return; } - if (!TShock.Utils.TilePlacementValid(tileX, tileY)) - { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tile placement valid) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); - args.Handled = true; - return; - } - if (action == EditAction.KillTile && Main.tile[tileX, tileY].type == TileID.MagicalIceBlock) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit super accepted from (ice block) {0} {1} {2}", args.Player.Name, action, editData); @@ -1654,6 +1653,13 @@ namespace TShockAPI short type = args.Type; short style = args.Style; + if (!TShock.Utils.TilePlacementValid(x, y)) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected valid placements from {0}", args.Player.Name); + args.Handled = true; + return; + } + if (type < 0 || type >= Main.maxTileSets) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected out of bounds tile from {0}", args.Player.Name); @@ -1702,14 +1708,6 @@ namespace TShockAPI return; } - if (!TShock.Utils.TilePlacementValid(x, y)) - { - TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected valid placements from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 1); - args.Handled = true; - return; - } - if (args.Player.Dead && TShock.Config.Settings.PreventDeadModification) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected dead people don't do things from {0}", args.Player.Name); @@ -1801,6 +1799,13 @@ namespace TShockAPI /// The packet arguments that the event has. internal void OnPlaceTileEntity(object sender, GetDataHandlers.PlaceTileEntityEventArgs args) { + if (!TShock.Utils.TilePlacementValid(args.X, args.Y)) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceTileEntity rejected tile placement valid from {0}", args.Player.Name); + args.Handled = true; + return; + } + if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceTileEntity rejected disabled from {0}", args.Player.Name); @@ -1828,6 +1833,13 @@ namespace TShockAPI /// The packet arguments that the event has. internal void OnPlaceItemFrame(object sender, GetDataHandlers.PlaceItemFrameEventArgs args) { + if (!TShock.Utils.TilePlacementValid(args.X, args.Y)) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceItemFrame rejected tile placement valid from {0}", args.Player.Name); + args.Handled = true; + return; + } + if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceItemFrame rejected disabled from {0}", args.Player.Name); @@ -2129,6 +2141,13 @@ namespace TShockAPI /// internal void OnFoodPlatterTryPlacing(object sender, GetDataHandlers.FoodPlatterTryPlacingEventArgs args) { + if (!TShock.Utils.TilePlacementValid(args.TileX, args.TileY)) + { + TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected tile placement valid from {0}", args.Player.Name); + args.Handled = true; + return; + } + if ((args.Player.SelectedItem.type != args.ItemID && args.Player.ItemInHand.type != args.ItemID)) { TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected item not placed by hand from {0}", args.Player.Name);