Skip to content

Commit 5569832

Browse files
authored
basic security resource as a foundation (#528)
1 parent 5bf553f commit 5569832

File tree

6 files changed

+172
-0
lines changed

6 files changed

+172
-0
lines changed

[admin]/security/NOTES.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
*** DISCLAIMER ***
2+
3+
This resource is very barebone and should be used as a learning foundation for security on your server.
4+
It only covers the most basic server events for detecting abusive behaviour and logs them without taking any action.
5+
There are many more ways to combat bad players with server and client scripting adapted to your server/gamemode.
6+
7+
As a general rule of thumb, following points should be considered:
8+
- never trust the client, if you accept data from client, validate it on server if they make any sense
9+
- use the variable "client" instead of "source" for custom server events, source can be faked, client not
10+
- try to avoid elementdatas, if you need elementdata to be synced to client and they should remain read only on client,
11+
add them to tblProtectedElementDatas in players.lua to prevent clients from updating them

[admin]/security/events.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- https://wiki.multitheftauto.com/wiki/OnPlayerTriggerInvalidEvent
2+
-- gets triggered when a remote clients triggers an invalid event on server
3+
function clientTriggersInvalidEvent(strEventName, bIsAdded, bIsRemote)
4+
logViolation(source, "Triggered invalid event \""..strEventName.."\" - bIsAdded: "..tostring(bIsAdded).." - bIsRemote: "..tostring(bIsRemote));
5+
end
6+
addEventHandler("onPlayerTriggerInvalidEvent", root, clientTriggersInvalidEvent);
7+
8+
9+
10+
-- https://wiki.multitheftauto.com/wiki/OnPlayerTriggerEventThreshold
11+
-- gets triggered when a remote clients exceeds the event trigger treshold set by server in config -> max_player_triggered_events_per_interval
12+
function clientTriggersEventThreshold()
13+
logViolation(source, "Exceeded event trigger threshold of "..tostring(getServerConfigSetting("max_player_triggered_events_per_interval")));
14+
end
15+
addEventHandler("onPlayerTriggerEventThreshold", root, clientTriggersEventThreshold);

[admin]/security/logging.lua

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
-- log messages triggered by player
2+
function logViolation(uPlayer, strMessage)
3+
local strPlayerName, strPlayerIP, strPlayerSerial = getPlayerName(uPlayer), getPlayerIP(uPlayer), getPlayerSerial(uPlayer);
4+
local strLogFileName = "violations.txt";
5+
local uFileHandle = fileExists(strLogFileName) and fileOpen(strLogFileName);
6+
7+
if(not uFileHandle) then
8+
uFileHandle = fileCreate(strLogFileName);
9+
fileFlush(uFileHandle);
10+
else
11+
fileSetPos(uFileHandle, fileGetSize(uFileHandle));
12+
end
13+
14+
local strViolationMessage = getDateTime().." CLIENT: "..strPlayerName.." | IP: "..strPlayerIP.." | SERIAL: "..strPlayerSerial.." | "..strMessage;
15+
16+
outputDebugString(strViolationMessage, 4, 255, 255, 255);
17+
outputServerLog(strViolationMessage);
18+
fileWrite(uFileHandle, strViolationMessage.."\n");
19+
fileClose(uFileHandle);
20+
end
21+
22+
23+
24+
-- log messages without player element
25+
function logAction(strMessage)
26+
local strLogFileName = "actions.txt";
27+
local uFileHandle = fileExists(strLogFileName) and fileOpen(strLogFileName);
28+
29+
if(not uFileHandle) then
30+
uFileHandle = fileCreate(strLogFileName);
31+
fileFlush(uFileHandle);
32+
else
33+
fileSetPos(uFileHandle, fileGetSize(uFileHandle));
34+
end
35+
36+
local strActionMessage = getDateTime().." "..strMessage;
37+
38+
outputDebugString(strActionMessage, 4, 255, 255, 255);
39+
outputServerLog(strActionMessage);
40+
fileWrite(uFileHandle, strActionMessage.."\n");
41+
fileClose(uFileHandle);
42+
end
43+
44+
45+
46+
-- get the current date and time for logging
47+
function getDateTime()
48+
local tblRealTime = getRealTime();
49+
local iDay = tblRealTime.monthday;
50+
local iMonth = tblRealTime.month + 1;
51+
local iYear = tblRealTime.year + 1900;
52+
local iHour = tblRealTime.hour;
53+
local iMinute = tblRealTime.minute;
54+
local iSecond = tblRealTime.second;
55+
56+
if(iDay < 10) then iDay = "0"..iDay end;
57+
if(iMonth < 10) then iMonth = "0"..iMonth end;
58+
if(iHour < 10) then iHour = "0"..iHour end;
59+
if(iMinute < 10) then iMinute = "0"..iMinute end;
60+
if(iSecond < 10) then iSecond = "0"..iSecond end;
61+
62+
return "["..tostring(iDay).."."..tostring(iMonth).."."..tostring(iYear).." - "..tostring(iHour)..":"..tostring(iMinute)..":"..tostring(iSecond).."]";
63+
end

[admin]/security/meta.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<meta>
2+
<info name="Security" author="-ffs-PLASMA" type="misc" version="1.0" description="Basic security functionality" />
3+
4+
<min_mta_version server="1.6.0-9.22470" />
5+
6+
<script src="logging.lua" type="server"/>
7+
<script src="events.lua" type="server"/>
8+
<script src="misc.lua" type="server"/>
9+
<script src="players.lua" type="server"/>
10+
</meta>

[admin]/security/misc.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- https://wiki.multitheftauto.com/wiki/OnSettingChange
2+
-- gets triggered when a resource setting has been changed
3+
function resourceSettingChanged(strSetting, strOldValue, strNewValue)
4+
logAction("Setting \""..strSetting.."\" has been changed from \""..fromJSON(strOldValue).."\" to \""..fromJSON(strNewValue).."\"");
5+
end
6+
addEventHandler("onSettingChange", root, resourceSettingChanged);
7+
8+
9+
10+
-- https://wiki.multitheftauto.com/wiki/OnAccountDataChange
11+
-- gets triggered when account has been changed
12+
function accountDataChanged(uAccount, strKey, strValue)
13+
logAction("Data \""..strKey.."\" of account \""..getAccountName(uAccount).."\" has been changed to \""..strValue.."\"");
14+
end
15+
addEventHandler("onAccountDataChange", root, accountDataChanged);

[admin]/security/players.lua

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
-- add the elementdatas you want to protect from client updates in here
2+
local tblProtectedElementDatas = {["Score"] = true};
3+
4+
5+
6+
-- https://wiki.multitheftauto.com/wiki/OnElementDataChange
7+
-- gets triggered when a client tries to change a synced elementdata, check if client is permitted to change that specific data
8+
-- also prevents one client changing the elementdata of another client
9+
function clientChangesElementData(strKey, varOldValue, varNewValue)
10+
if(client and (tblProtectedElementDatas[strKey] or client ~= source)) then
11+
logViolation(client, "Tried to change elementdata \""..tostring(strKey).."\" of resource \""..tostring(sourceResource).."\" from \""..tostring(varOldValue).."\" to \""..tostring(varNewValue).."\"");
12+
setElementData(source, strKey, varOldValue);
13+
end
14+
end
15+
addEventHandler("onElementDataChange", root, clientChangesElementData);
16+
17+
18+
19+
-- https://wiki.multitheftauto.com/wiki/OnPlayerACInfo
20+
-- gets triggered when AC detects something for client on connect
21+
function clientNotifyACInfo(tblDetectedACList, iD3D9Size, strD3D9MD5, strD3D9SHA256)
22+
logViolation(source, "AC list detected: "..table.concat(tblDetectedACList, ",").." - D3D9Size: "..tostring(iD3D9Size).." - D3D9MD5: "..tostring(strD3D9MD5));
23+
end
24+
addEventHandler("onPlayerACInfo", root, clientNotifyACInfo);
25+
26+
27+
28+
-- https://wiki.multitheftauto.com/wiki/OnPlayerModInfo
29+
-- gets triggered when client joins server with modified game files
30+
function clientNotifyModInfo(strFileName, tblItemList)
31+
for _, strItemName in ipairs(tblItemList) do
32+
logViolation(source, "Mod detected - file: "..strFileName.." - GTA ID: "..strItemName.id.." - GTA name: "..strItemName.name);
33+
end
34+
end
35+
addEventHandler("onPlayerModInfo", root, clientNotifyModInfo);
36+
37+
38+
39+
-- force all connected players to send their AC/Mod info on resource start
40+
addEventHandler("onResourceStart", resourceRoot, function()
41+
for _, uPlayer in ipairs(getElementsByType("player")) do
42+
resendPlayerModInfo(uPlayer);
43+
resendPlayerACInfo(uPlayer);
44+
end
45+
end);
46+
47+
48+
49+
-- https://wiki.multitheftauto.com/wiki/OnPlayerNetworkStatus
50+
-- gets triggered when connection from server to a client is interrupted
51+
function clientNetworkStatus(iStatus, iTicks)
52+
if(iStatus == 0) then
53+
logViolation(source, "Network interruption has began after "..iTicks.." ticks");
54+
elseif(iStatus == 1) then
55+
logViolation(source, "Network interruption has stopped after "..iTicks.." ticks");
56+
end
57+
end
58+
addEventHandler("onPlayerNetworkStatus", root, clientNetworkStatus);

0 commit comments

Comments
 (0)