Skip to content

Commit

Permalink
Fix exploit.
Browse files Browse the repository at this point in the history
Fixes an exploit where a cheater could modify an item with a table full of junk data (randomly generated strings in my case) to lag the server. It lags the server due to RAM usage from storing it, Filling up the database where items are stored with modifications, and networking all that junk data which also causes script errors due to their being too much.

This is fixed by creating an item function, SanitizeTable, that takes modifications as a parameter and returns a new modifications table with only the data it should contain. If an item does not have a SanitizeTable function defined a default one which allows only text and color modifications to pass is used. This may break some custom items that rely on modifications other than text and color, but it's worth it to prevent people from DoSing the server.

In addition a minor optimization that prevents creating multiple (6) empty functions per item is included. Instead of creating a new empty function for Items to initialize certain values, it sets the value to a premade empty function.
  • Loading branch information
end360 committed Sep 12, 2018
1 parent 25ca32a commit fbed370
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 33 deletions.
54 changes: 31 additions & 23 deletions lua/pointshop/items/headshatsmasks/texthat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,39 @@ ITEM.NoPreview = true
local MaxTextLength = 32

function ITEM:PostPlayerDraw(ply, modifications, ply2)
if not ply == ply2 then return end
if not ply:Alive() then return end
if ply.IsSpec and ply:IsSpec() then return end
local offset = Vector(0, 0, 79)
local ang = LocalPlayer():EyeAngles()
local pos = ply:GetPos() + offset + ang:Up()
ang:RotateAroundAxis(ang:Forward(), 90)
ang:RotateAroundAxis(ang:Right(), 90)
cam.Start3D2D(pos, Angle(0, ang.y, 90), 0.1)
draw.DrawText(string.sub(modifications.text or ply:Nick(), 1, MaxTextLength), "PS_Heading", 2, 2, modifications.color or Color(255, 255, 255, 255), TEXT_ALIGN_CENTER)
cam.End3D2D()
if not ply == ply2 then return end
if not ply:Alive() then return end
if ply.IsSpec and ply:IsSpec() then return end
local offset = Vector(0, 0, 79)
local ang = LocalPlayer():EyeAngles()
local pos = ply:GetPos() + offset + ang:Up()
ang:RotateAroundAxis(ang:Forward(), 90)
ang:RotateAroundAxis(ang:Right(), 90)
cam.Start3D2D(pos, Angle(0, ang.y, 90), 0.1)
draw.DrawText(string.sub(modifications.text or ply:Nick(), 1, MaxTextLength), "PS_Heading", 2, 2, modifications.color or Color(255, 255, 255, 255), TEXT_ALIGN_CENTER)
cam.End3D2D()
end

function ITEM:Modify(modifications)
Derma_StringRequest("Text", "What text do you want your hat to say?", "", function(text)
if string.find(text, "#") then
text = string.gsub(text, "#", "")
end
modifications.text = string.sub(text, 1, MaxTextLength)
PS:ShowColorChooser(self, modifications)
end)
Derma_StringRequest("Text", "What text do you want your hat to say?", "", function(text)
if string.find(text, "#") then
text = string.gsub(text, "#", "")
end
modifications.text = string.sub(text, 1, MaxTextLength)
PS:ShowColorChooser(self, modifications)
end)
end


-- Since this item has modifications we return a table of only what should be allowed for security reasons
function ITEM:SanitizeTable( modifications )
local tab = {}
tab.text = modifications.text and string.sub(modifications.text, 1, MaxTextLength) or nil
tab.color = modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255, 255) or Color(255,255,255)
return tab
end
7 changes: 6 additions & 1 deletion lua/pointshop/items/trails/electric.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ end
function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.ElectricTrail)
self:OnEquip(ply, modifications)
end
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end
5 changes: 5 additions & 0 deletions lua/pointshop/items/trails/laser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.LaserTrail)
self:OnEquip(ply, modifications)
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end
6 changes: 6 additions & 0 deletions lua/pointshop/items/trails/loltrail.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.LolTrail)
self:OnEquip(ply, modifications)
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end

6 changes: 6 additions & 0 deletions lua/pointshop/items/trails/lovetrail.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.LoveTrail)
self:OnEquip(ply, modifications)
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end

5 changes: 5 additions & 0 deletions lua/pointshop/items/trails/plasmatrail.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.PlasmaTrail)
self:OnEquip(ply, modifications)
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end
5 changes: 5 additions & 0 deletions lua/pointshop/items/trails/smoke.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.SmokeTrail)
self:OnEquip(ply, modifications)
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end
5 changes: 5 additions & 0 deletions lua/pointshop/items/trails/tube.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ function ITEM:OnModify(ply, modifications)
SafeRemoveEntity(ply.TubeTrail)
self:OnEquip(ply, modifications)
end

-- Since trails allow players to change the color we limit the table to only color for security reasons
function ITEM:SanitizeTable( modifications )
return {color=modifications.color and Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255) or nil}
end
15 changes: 8 additions & 7 deletions lua/pointshop/sh_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ end

function PS:LoadItems()
local _, dirs = file.Find('pointshop/items/*', 'LUA')

local emptyfunc = function() end

for _, category in pairs(dirs) do
local f, _ = file.Find('pointshop/items/' .. category .. '/__category.lua', 'LUA')

Expand All @@ -72,7 +73,7 @@ function PS:LoadItems()
CATEGORY.AllowedEquipped = -1
CATEGORY.AllowedUserGroups = {}
CATEGORY.CanPlayerSee = function() return true end
CATEGORY.ModifyTab = function(tab) return end
CATEGORY.ModifyTab = emptyfunc

if SERVER then AddCSLuaFile('pointshop/items/' .. category .. '/__category.lua') end
include('pointshop/items/' .. category .. '/__category.lua')
Expand Down Expand Up @@ -107,11 +108,11 @@ function PS:LoadItems()
ITEM.CanPlayerEquip = true
ITEM.CanPlayerHolster = true

ITEM.OnBuy = function() end
ITEM.OnSell = function() end
ITEM.OnEquip = function() end
ITEM.OnHolster = function() end
ITEM.OnModify = function() end
ITEM.OnBuy = emptyfunc
ITEM.OnSell = emptyfunc
ITEM.OnEquip = emptyfunc
ITEM.OnHolster = emptyfunc
ITEM.OnModify = emptyfunc
ITEM.ModifyClientsideModel = function(ITEM, ply, model, pos, ang)
return model, pos, ang
end
Expand Down
19 changes: 17 additions & 2 deletions lua/pointshop/sv_player_extension.lua
Original file line number Diff line number Diff line change
Expand Up @@ -429,16 +429,31 @@ function Player:PS_HolsterItem(item_id)
self:PS_SendItems()
end

-- modify items

local function Sanitize( modifications ) -- used as a default if an item is missing the SanitizeTable function. Catches colors/text
local out = {}
if isstring(modifications.text) then out.text = modifications.text end
if modifications.color then
out.color = Color(modifications.color.r or 255, modifications.color.g or 255, modifications.color.b or 255)
end
return out
end

function Player:PS_ModifyItem(item_id, modifications)
if not PS.Items[item_id] then return false end
if not self:PS_HasItem(item_id) then return false end
if not type(modifications) == "table" then return false end
if not self:PS_CanPerformAction(item_id) then return false end

local ITEM = PS.Items[item_id]

-- This if block helps prevent someone from sending a table full of random junk that will fill up the server's RAM, be networked to every player, and be stored in the database
if ITEM.SanitizeTable then
modifications = ITEM:SanitizeTable(modifications)
else
modifications = Sanitize(modifications)
end

for key, value in pairs(modifications) do
self.PS_Items[item_id].Modifiers[key] = value
end
Expand Down

0 comments on commit fbed370

Please sign in to comment.