Roblox verwendet ein verteiltes physikalisches System, in dem Clients die physische Simulation von Objekten in ihrer Kontrolle übernehmen, typischerweise den Charakter des Spieler:inund unverankerte Objekte in der Nähe dieses Charakters.Darüber hinaus können Exploiter durch die Verwendung von Drittsoftware willkürlichen Luau-Code auf dem Client ausführen, um das Datenmodell ihres Clients zu manipulieren und den Code, der darauf ausgeführt wird, zu dekompilieren und anzuzeigen.
Zusammen bedeutet dies, dass ein erfahrener Exploiter möglicherweise Code ausführen kann, um in deinem Spiel zu betrügen, einschließlich:
- Teleportieren ihres eigenen Charakters rund um den Ort.
- Schießen ungesichert RemoteEvents oder invozieren RemoteFunctions, z. B. um sich Items zuzuweisen, ohne sie zu verdienen.
- Anpassen ihrer Charakter WalkSpeed so, dass er sich sehr schnell bewegt.
Während du begrenzte Designverteidigungen implementieren kannst, um gemeinsame Angriffe zu erfassen, wird dringend empfohlen, dass du zuverlässigere Server-Seiten-Abwehrtaktiken implementierst, da der Server die letzte Autorität für jede ausgeführte Erlebnisist.
Defensive Design-Taktiken
Grundlegende Designentscheidungen können als "erste Schritte"-Sicherheitsmaßnahmen dienen, um Exploits zu verhindern.Zum Beispiel in einem Shooter-Spiel, in dem Spieler Punkte für das Töten anderer Spieler erhalten, kann ein Exploiter eine Reihe von Bots erstellen, die sich an denselben Ort teleportieren, damit sie schnell für Punkte getötet werden können.Angesichts dieser möglichen Exploit betrachte zwei Ansätze und ihr vorhersehbares Ergebnis:
Ansatz | Vorhersehbares Ergebnis |
---|---|
Verfolge Bots, indem du Code schreibst, der versucht, sie zu erkennen. | |
Reduziere oder entferne komplette Punktegewinne für Tötungen bei neu gespawnten Spielern. |
Während das defensive Design natürlich nicht die perfekte oder umfassende Lösung ist, kann es zu einem breiteren Sicherheitsansatz beitragen, zusammen mit Server-seitiger Minderung.
Serverseitige Linderung
Soweit wie möglich sollte der Server das endgültige Urteil darüber abgeben, was "wahr" ist und was der aktuelle Zustand der Welt ist.Clients können natürlich den Server bitten, Änderungen vorzunehmen oder eine Actionauszuführen, aber der Server sollte jede dieser Änderungen/Aktionen validieren und genehmigen bevor die Ergebnisse auf andere Spieler repliziert werden.
Mit Ausnahme bestimmter Physikoperationen werden Änderungen am Datenmodell auf dem Client nicht auf den Server repliziert, so dass der Hauptangriffsweg oft über die Netzwerkereignisse ist, die du mit RemoteEvents und RemoteFunctions deklariert hast.Denken Sie daran, dass ein Exploiter, der seinen eigenen Code auf Ihrem Client ausführt, diese mit den Daten aufrufen kann, die er möchte.
Remote-Laufzeittyp-Validierung
Ein Angriffsweg ist für einen Exploiter, um RemoteEvents und RemoteFunctions mit Argumenten des falschen eingebenaufzurufen.In einigen Szenarien kann dies dazu führen, dass Code auf dem Server, der auf diese Remotes hört, auf eine Weise fehlerhaft wird, die dem Exploiter zugute kommt.
Wenn Sie remote-Ereignisse/Funktionen verwenden, können Sie diesen Angriffstyp verhindern, indem Sie die Typen der übergebenen Argumente auf dem Server validieren.Das Modul "t" , verfügbar hier, ist nützlich für die Typprüfung auf diese Weise.Zum Beispiel, unter der Annahme, dass der Code des Moduls als ModuleScript mit dem Namen t innerhalb von ReplicatedStorage existiert:
Lokales Skript in StarterPlayerScripts
local ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")-- Passen Sie Farbe und Position des Teils beim Aufrufen der Funktion anlocal newPart = remoteFunction:InvokeServer(Color3.fromRGB(200, 0, 50), Vector3.new(0, 25, 0))if newPart thenprint("The server created the requested part:", newPart)elseif newPart == false thenprint("The server denied the request. No part was created.")end
Skript in ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
local t = require(ReplicatedStorage:WaitForChild("t"))
-- Erstellen Sie einen Typ-Validierer im Voraus, um unnötige Aufwendungen zu vermeiden
local createPartTypeValidator = t.tuple(t.instanceIsA("Player"), t.Color3, t.Vector3)
-- Erstelle ein neues Teil mit den übergebenen Eigenschaften
local function createPart(player, partColor, partPosition)
-- Typprüfung der übergebenen Argumente
if not createPartTypeValidator(player, partColor, partPosition) then
-- Stell "false" leise zurück, wenn die Typprüfung hier fehlschlägt
-- Einen Fehler ohne Abklingzeit zu erheben, kann missbraucht werden, um den Server zu verlangsamen
-- Geben Sie stattdessen Feedback des Clients an!
return false
end
print(player.Name .. " requested a new part")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
return newPart
end
-- Binden Sie "createPart()" an den Rückruf der Remotefunktion
remoteFunction.OnServerInvoke = createPart
Daten验证
Ein weiterer Angriff, den Exploiter möglicherweise starten, ist, technisch gültige Arten zu senden aber sie extrem groß, lang oder sonst fehlerhaft zu machen.Wenn zum Beispiel der Server eine teure Operation an einer Zeichenkette durchführen muss, die mit der Länge skaliert, könnte ein Exploiter eine unglaublich große oder fehlerhafte Zeichenkette senden, um den Server zu verlangsamen.
Ebenso werden sowohl als auch zu , aber beide können große Probleme verursachen, wenn ein Exploiter sie sendet und sie nicht durch Funktionen wie die gefolgte Profilerichtig behandelt werden:
local function isNaN(n: number): boolean
-- NaN ist nie gleich selbst
return n ~= n
end
local function isInf(n: number): boolean
-- Die Zahl könnte -inf oder inf sein
return math.abs(n) == math.huge
end
Ein weiterer häufiger Angriff, den Exploiter verwenden können, besteht darin, tables anstelle von Instance zu senden.Komplexe Payloads können das nachahmen, was eine sonst gewöhnliche Objektreferenz wäre.
Zum Beispiel, mit einem In-Experience-Shop -System ausgestattet, in dem Artikeldaten wie Preise in NumberValue Objekten gespeichert sind, kann ein Exploiter alle anderen Überprüfungen umgehen, indem er gefolgte Profiletut:
Lokales Skript in StarterPlayerScripts
local ReplicatedStorage = game:GetService("ReplicatedStorage")local itemDataFolder = ReplicatedStorage:WaitForChild("ItemData")local buyItemEvent = ReplicatedStorage:WaitForChild("BuyItemEvent")local payload = {Name = "Ultra Blade",ClassName = "Folder",Parent = itemDataFolder,Price = {Name = "Price",ClassName = "NumberValue",Value = 0, -- Negative Werte könnten auch verwendet werden, was dazu führt, dass Währung gegeben wird, anstatt sie zu nehmen!},}-- Sende bösartige Zahlung an den Server (dies wird abgelehnt)print(buyItemEvent:InvokeServer(payload)) -- Gibt "false Invalid item provided" aus-- Sende ein echtes Element an den Server (das wird durchgehen!)print(buyItemEvent:InvokeServer(itemDatafolder["Real Blade"])) -- Outputs "true" and remaining currency if purchase succeeds
Skript in ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local itemDataFolder = ReplicatedStorage:WaitForChild("ItemData")
local buyItemEvent = ReplicatedStorage:WaitForChild("BuyItemEvent")
local function buyItem(player, item)
-- Überprüfe, ob das übermittelte Element nicht spoofed wird und sich im Ordner ItemData befindet
if typeof(item) ~= "Instance" or not item:IsDescendantOf(itemDataFolder) then
return false, "Invalid item provided"
end
-- Der Server kann dann fortfahren, die Bestellung gemäß dem Beispielfluss unten zu verarbeiten
end
-- Binden Sie "buyItem()" an den Rückruf der Remotefunktion
buyItemEvent.OnServerInvoke = buyItem
Wert-Validierung
Zusätzlich zur Validierung von Arten und Daten , solltest du die Werte , die durch und übermittelt wurden, validieren, um sicherzustellen, dass sie im angeforderten Kontext gültig und logisch sind.Zwei häufige Beispiele sind ein Erlebnisladen und ein Waffenzielsystem.
kaufen
Betrachte ein Erlebnisshop-System mit Benutzeroberfläche, zum Beispiel ein Produktauswahlmenü mit einer "Kaufen"-Schaltfläche.Wenn der Knopf gedrückt wird, kannst du eine RemoteFunction zwischen dem Client und dem Server aufrufen, um den Kauf zu beantragen.Es ist jedoch wichtig, dass der Server , der zuverlässigste Manager des Erlebnisses, bestätigt, dass der Benutzer genug Geld hat, um das Artikelzu kaufen.

Waffenzielung
Kampfszenarien erfordern besondere Aufmerksamkeit bei der Überprüfung von Werten, insbesondere durch Ziel- und Treffer验证.
Stell dir ein Spiel vor, in dem ein Spieler einen Laserstrahl auf einen anderen Spieler:inabfeuern kann.Anstatt der Client dem Server mitzuteilen, wen er beschädigen soll, sollte er stattdessen dem Server die Herkunftsposition des Schusses und die Teil-/Position, die er getroffen hat, mitteilen.Der Server kann dann das gefolgte Profilevalidieren:
Die Position, die der Client berichtet schießt von ist in der Nähe des Charakters des Spieler:inauf dem Server.Beachten Sie, dass der Server und der Client aufgrund der Verzögerung leicht unterschiedlich sind, so dass zusätzliche Toleranz anfallen muss.
Die Position, die der Client berichtet trifft ist ziemlich nahe an der Position der Teil , die der Client berichtet, auf dem Server.
Es gibt keine statischen Hindernisse zwischen der Position, von der der Client berichtet, und der Position, auf die der Client berichtet.Diese Prüfung gewährleistet, dass ein Client nicht versucht, durch Wände zu schießen.Beachten Sie, dass dies nur die statische Geometrie überprüfen sollte, um gültige Schüsse aufgrund von Verzögerung abzulehnen. Zusätzlich , möglicherweise möchten Sie weitere serverseitige Validierungen wie folgt implementieren:
Verfolge, wann der Spieler zuletzt seine Waffe abgefeuert hat, und validiere, um sicherzustellen, dass er nicht zu schnell schießt.
Verfolge die Munitionsmenge eines jeden Spieler:inauf dem Server und bestätige, dass ein abfeuernder Spieler genug Munition hat, um den Waffenangriff auszuführen.
Wenn du Teams implementiert hast oder ein "Spieler gegen Bot"-Kampfssystem, bestätige, dass der getroffene Charakter ein Feind ist, nicht ein Teamkollege.
Bestätigen, dass der getroffene Spieler lebt.
Lagere Waffen- und Spielerzustand auf dem Server und bestätige, dass ein feuernder Spieler durch keine aktuelle Aktion wie Nachladen oder einen Zustand wie Sprinten blockiert wird.
Datenspeicher-Manipulation
In Erlebnissen, die DataStoreService verwenden, um Spielerdaten zu speichern, können Exploiter von ungültigen Daten und geheimnisvolleren Methoden profitieren, um zu verhindern, dass ein DataStore richtig gespeichert wird.Dies kann insbesondere bei Erfahrungen mit Artikelhandel, Marktplätzen und ähnlichen Systemen missbraucht werden, bei denen Artikel oder Währungen das Inventar eines Spieler:inverlassen.
Stellen Sie sicher, dass alle Aktionen, die durch eine RemoteEvent oder RemoteFunction ausgeführt werden, die Spielerdaten mit Client-Eingabe beeinflussen, gemäß dem gefolgte Profilesaniert werden:
- Instance Werte können nicht in eine DataStore serialize und werden fehlschlagen. Verwende Typ-Validierung, um dies zu verhindern.
- DataStores haben Datenlimits.Schnüre mit willkürlicher Länge sollten überprüft und/oder begrenzt werden, um dies zu vermeiden, während sichergestellt wird, dass unbegrenzte willkürliche Schlüssel vom Client nicht zu Tabellen hinzugefügt werden können.
- Tabellenindizes können nicht NaN oder nil sein. Iteriere über alle Tabellen, die vom Client übermittelt wurden, und überprüfe, dass alle Indizes gültig sind.
- DataStores kann nur gültige UTF-8-Zeichen akzeptieren, so solltest du alle Zeichen, die vom Client bereitgestellt werden, via utf8.len() validieren, um sicherzustellen, dass sie gültig sind. utf8.len() wird die Länge einer Stringzurückgeben, die UTF-8-Zeichen als einen einzelnen Zeichen behandelt; wenn ein ungültiger UTF-8-Zeicher gefunden wird, wird er nil und die Position des ungültigen Zeichens zurückgeben.Beachten Sie, dass ungültige UTF-8-Zeichen auch in Tabellen als Schlüssel und Werte vorhanden sein können.
Fernsteuerung beschleunigen
Wenn ein Client in der Lage ist, deinen Server mit einer kostspieligen Operation abzuschließen oder einen beschränkten Dienst wie DataStoreService über einen RemoteEvent aufrufen kann, ist es kritisch, dass du Rate-Limitierung implementierst, um sicherzustellen, dass die Operation nicht zu häufig aufgerufen wird.Die Geschwindigkeitsbegrenzung kann durch das Nachverfolgen verwirklicht werden, wenn der Client zuletzt ein Remote-Ereignis aufgerufen hat und die nächste Anfrage ablehnt, wenn sie zu früh aufgerufen wird.
Bewegungs验证ung
Für wettbewerbsfähige Erlebnisse möchten Sie möglicherweise die Bewegungen des Spielers auf dem Server validieren, um sicherzustellen, dass sie nicht um die Karte herum teleportieren oder schneller als akzeptabel sind.
In Schritten von 1 Sekunde überprüfe den neuen Standort des Charakters gegen einen zuvor gespeicherten Standort.
Vergleichen Sie den tatsächlichen Distanzen-Delta gegen den tolerierbaren Delta und fahren Sie wie folgt fort:
- Für einen tolerierbaren Delta speichere den neuen Standort des Charakters in Vorbereitung auf die nächste erhöhte überprüfen.
- Für ein unerwartetes oder unerträgliches Delta (mögliche Geschwindigkeit/Teleport-Exploit):
- Erhöhe einen separaten "Anzahl der Verstöße"-Wert für den Spieler:in, versus die Bestrafung für ein "falsches Positiv" aufgrund extremer Serververzögerung oder anderer Nicht-Exploit-Faktoren.
- Wenn eine große Anzahl von Verstößen über einen Zeitraum von 30-60 Sekunden auftritt, Kick() den Spieler aus der Erfahrung vollständig zurücksetzen; sonst setze die Zahl der Verstöße zurück.Beachten Sie, dass beim Treten eines Spielers wegen Betrugs die beste Praxis ist, das Ereignis aufzuzeichnen, damit Sie verfolgen können, wie viele Spieler betroffen sind.