replace urls in html and javascript with safe urls

This commit is contained in:
Pierce 2023-08-21 21:47:39 -04:00
parent fef959f369
commit 29b51b1e8e
No known key found for this signature in database
GPG Key ID: EC79465B0E865E47
7 changed files with 122 additions and 40 deletions

View File

@ -0,0 +1,69 @@
CFCHTTP.version = "1.0.0"
local messages = {}
hook.Add( "PlayerInitialSpawn", "myAddonName/Load", function( ply )
if ply:IsSuperAdmin() then
timer.Simple( 30, function()
for _, msg in ipairs( messages ) do
ply:ChatPrint( msg )
end
end )
end
end )
local function notify( msg )
table.insert( messages, msg )
end
---@param v string
---@param v2 string
---@return boolean
--- returns true if v is newer than v2
local function isVersionNewer( v, v2 )
local splitNewVersion = string.Split( v, "." )
local newMajor, newMinor, newPatch = tonumber( splitNewVersion[1] ), tonumber( splitNewVersion[2] ), tonumber( splitNewVersion[3] )
local splitOldVersion = string.Split( v2, "." )
local oldMajor, oldMinor, oldPatch = tonumber( splitOldVersion[1] ), tonumber( splitOldVersion[2] ), tonumber( splitOldVersion[3] )
if newMajor ~= oldMajor then
return newMajor > oldMajor
end
if newMinor ~= oldMinor then
return newMinor > oldMinor
end
if newPatch ~= oldPatch then
return newPatch > oldPatch
end
return false
end
hook.Add( "Think", "CFCHTTP_UpdateCheck", function()
hook.Remove( "Think", "CFCHTTP_UpdateCheck" )
local http = _HTTP or HTTP
http {
url = "https://raw.githubusercontent.com/CFC-Servers/cfc_cl_http_whitelist/main/update.json",
method = "GET",
success = function( code, body, headers )
local data = util.JSONToTable( body )
if not data then return end
if not data.version then
return
end
if data.version == CFCHTTP.version then
return
end
if not isVersionNewer( data.minimumVersion, CFCHTTP.version ) then
return
end
notify( "\n" )
notify( "Your version of CFC HTTP Whitelist is bellow the minimum safe version." )
notify( "Please update to the latest version." )
notify( "\n" )
end
}
end )

2
gluatest.yaml Normal file
View File

@ -0,0 +1,2 @@
config:
gamemode: sandbox

View File

@ -1,5 +0,0 @@
{
"diagnostics.globals": [
"expect"
]
}

View File

@ -168,44 +168,40 @@ local function wrapHTMLPanel( panelName )
_G[runJavascript] = _G[runJavascript] or controlTable.RunJavascript
controlTable.SetHTML = function( self, html, ... )
local urls, err = CFCHTTP.FileTypes.HTML.GetURLSFromData( html )
local options = CFCHTTP.GetOptionsForURLs( urls )
local isAllowed
if #urls == 0 then
isAllowed = true
else
isAllowed = err == nil and options.combined and options.combined.allowed
end
local stack = string.Split( debug.traceback(), "\n" )
logRequest( "GET", options.combinedUri, stack[3], isAllowed )
if not isAllowed then
html = [[<h1>BLOCKED By CFC HTTP Whitelist</h1>]]
end
html = CFCHTTP.ReplaceURLs( html, function( url )
local options = CFCHTTP.GetOptionsForURL( url )
local isAllowed = options and options.allowed
local noisy = true -- this will be really spammy so set it to noisy by default
logRequest( "GET", url, stack[3], isAllowed, noisy )
if not isAllowed then
return CFCHTTP.GetRedirectURL( url )
end
return url
end )
return _G[setHTML]( self, html, ... )
end
controlTable.RunJavascript = function( self, js )
local urls, err = CFCHTTP.FileTypes.HTML.GetURLSFromData( js )
local options = CFCHTTP.GetOptionsForURLs( urls )
local isAllowed
if #urls == 0 then
return _G[runJavascript]( self, js )
else
isAllowed = err == nil and options.combined and options.combined.allowed
end
local stack = string.Split( debug.traceback(), "\n" )
logRequest( "GET", options.combinedUri, stack[3], isAllowed )
js = CFCHTTP.ReplaceURLs( js, function( url )
local options = CFCHTTP.GetOptionsForURL( url )
local isAllowed = options and options.allowed
local noisy = true -- this will be really spammy so set it to noisy by default
if not isAllowed then
return
end
logRequest( "GET", url, stack[3], isAllowed, noisy )
if not isAllowed then
return CFCHTTP.GetRedirectURL( url )
end
return url
end )
return _G[runJavascript]( self, js )
end
@ -223,6 +219,9 @@ local function wrapHTMLPanel( panelName )
end
end
wrapHTMLPanel( "DHTML" )
wrapHTMLPanel( "DPanel" )
wrapHTMLPanel( "DMediaPlayerHTML" )
hook.Add( "Initialize", "CFC_HttpWhitelist_WrapHTML", function()
if CFCHTTP.config.wrapHTMLPanels then
wrapHTMLPanel( "DHTML" )

View File

@ -20,6 +20,9 @@ local config = {
allowed = false,
},
addresses = {
-- this is used internally by this addon, removing it could cause issues
["gmhttp.pages.dev"] = { allowed = true, noisy = true, permanent = true },
["google.com"] = { allowed = true, noisy = true },
["www.google.com"] = { allowed = true, noisy = true },

View File

@ -6,7 +6,7 @@
CFCHTTP.URLPattern = "(%a+)://([^:/ \t]+):?(%d*)/?.*"
CFCHTTP.URLPatternNoGroups = "%a+://[^:/ \t\"]+:?%d*/?[^\n\" ]*"
CFCHTTP.URLPatternNoGroups = "%a+://[^:/ \t\"]+:?%d*/?[^\n\" \\]*"
---@param url string
---@return URLData
@ -34,8 +34,23 @@ function CFCHTTP.FindURLs( text )
return urls
end
function CFCHTTP.GetRedirectURL( url )
url = string.Replace( url, "\n", "" )
url = string.Trim( url )
local b64 = util.Base64Encode( url, true )
return string.format( "https://gmhttp.pages.dev/redirect?url=%s", b64 )
end
---@param text string
---@param f fun( url:string ):string
---@return string
function CFCHTTP.ReplaceURLs( text, f )
local html = string.gsub( text, CFCHTTP.URLPatternNoGroups, f )
return html
end
local parsedAddressCache = {}
---@parm url string
---@param url string
---@return string|nil
function CFCHTTP.GetAddress( url )
if not url then return end

View File

@ -19,12 +19,11 @@ local htmlBlobs = [[
</html>
]]
return {
---@type GLuaTestTestGroup
local group = {
groupName = "CFC HTTP Whitelist Domains",
cases = {
{
timeout = 3,
async = false,
name = "Should get addresses from urls",
func = function()
for _, urlData in pairs( testUrls ) do
@ -40,8 +39,6 @@ return {
end
},
{
timeout = 3,
async = false,
name = "Get address should return expected data",
func = function()
for _, urlData in pairs( testUrls ) do
@ -52,3 +49,5 @@ return {
},
}
}
return group