I used the following rules to call the lua scripts.
#Store the sessionid in tx.sessionid
REQUEST_COOKIES:'/(j?sessionid|(php)?sessid|(asp|jserv|jw)?session[-_]?(id)?|cf(id|token)|sid)/' "(\d{4,4})?([^\s]+?)[\:\.\;\s]" "phase:1,id:'33000',t:none,capture,pass,nolog,setvar:tx.sessionid=%{TX.2}"
#if it's a post request check if the hidden fields are modified.
SecRule &ARGS_POST_NAMES "!@eq 0" \
"phase:2,t:none,t:lowercase,nolog,pass,id:'33001',exec:/test/read-hidden-values-memcached.lua"
SecRule TX:PARAMETER_TAMPERING ".*" "phase:2,t:none,log,deny,msg:'Parameter Tampering; Hidden field.',id:'3002',logdata:'Location: %{matched_var}',tag:'PARAMETER_TAMPERING'"
#Store the sessionid in tx.sessionid
SecRule RESPONSE_HEADERS:/Set-Cookie2?/ "(?i:(j?sessionid|(php)?sessid|(asp|jserv|jw)?session[-_]?(id)?|cf(id|token)|sid)=(\d{4,4})?([^\s]+?)[\:\.\;\s])" "phase:3,id:'33003',t:none,pass,nolog,capture,setvar:tx.sessionid=%{TX.7}"
#if a sessionid is there save the hidden fields into the backend.
SecRule TX:SESSIONID "(.*)" "chain,phase:4,id:'33004',t:none,pass,nolog"
SecRule RESPONSE_BODY ".*" "t:none,nolog,exec:/test/write-hidden-values-memcached.lua"
The 2 Rules which extract the sessionid are from the CRS file modsecurity_crs_16_session_hijacking.conf.
I only modified the regex so it would save the real sessionid and not the sessionid with the server identifier.
I only modified the regex so it would save the real sessionid and not the sessionid with the server identifier.
Here the two lua scripts.
read-hidden-values-memcached.lua:
function main()
require ('Memcached')
jsessionid = m.getvar("tx.sessionid", "none")
if jsessionid then
m.log(9, "luascript: SESSIONID=\"" .. jsessionid .. "\"")
else
return 'no sessionid'
end
argspost = m.getvars("ARGS_POST_NAMES", "none");
memcache = Memcached.Connect({{'server1',9999},{'server2',9999}})
if memcache then
-- Examine all variables
for i=1, #argspost do
argname = argspost[i].value
modsecargname = "ARGS_POST." .. argname
-- use to make exception per ARG
if modsecargname == "ARGS_POST.xxx" or modsecargname == "ARGS_POST.xxx1" or modsecargname == "ARGS_POST.xxx2" then
m.log(9, "luascript: ARGNAME matched exception so no further processing")
else
memvalue = memcache:get(jsessionid .. argname)
if memvalue then
arg = m.getvars(modsecargname, "none")
if memvalue == string.format("\"%s\"", arg[1].value) then
m.log(9, "luascript: value matched, value = " .. arg[1].value .."")
else
m.setvar("tx.parameter_tampering", "Parameter tampered = " .. modsecargname .. " old value = " .. memvalue .. " new value = " .. arg[1].value)
end
end
end
end
else
m.log(9, "luascript: error in connect to memcache")
end
-- Nothing wrong found.
memcache:disconnect_all()
end
write-hidden-values-memcached.lua
function main()
require ('Memcached')
jsessionid = m.getvar("tx.sessionid", "none")
if jsessionid then
m.log(9, "luascript: SESSIONID" .. jsessionid .. ".")
fh = assert (io.tmpfile()) -- open temporary file
responsebody = m.getvar("RESPONSE_BODY", "none")
if responsebody then
fh:write(responsebody)
fh:flush()
else
fh:close() -- close file
return 'no Response Body'
end
fh:seek ("set", 0) -- back to start
-- read whole file with '*a'
local tbuff = fh:read ("*a")
m.log(9, "luascript: read done from file")
fh:close() -- close file
memcache = Memcached.Connect({{'server1',9999},{'server2',9999}})
if memcache then
for a in string.gmatch(tbuff, "<input .->") do
t = {}
m.log(9, "a = " .. a)
for k, v in string.gmatch(a, "(%w+)=\"(.-)\"") do
t[k]=v
-- m.log(9, "var = " .. k .. " = " .. v .. "")
end
if t.type == nil then
t.type = ''
end
if t.value == nil then
t.value = ''
end
if t.name == nil then
t.name = ''
end
if t.type:lower() == "hidden" and t.value ~= '' and t.name ~= '' then
memname = t.name
memvalue = string.format("\"%s\"", t.value)
memcache:set(jsessionid .. memname, memvalue,600)
end
end
-- str1 = string.format('Response body is: %s\n', var1)
else
m.log(9, "luascript: error in connect to memcache")
end
memcache:disconnect_all()
else
m.log(9, "luascript: no sessionid")
end
m.log(9, "luascript: script end")
end
Now your hidden fields should be protected.
You should use these Rules in combination with the session hijacking rules in order to protect your session too.
prerequisite: lua, luamemcached, luasocket
The next time i think i will post how you can modify the modsecurity_crs_16_session_hijacking.conf file in order to be HA aware and store the session data in memcached/kyoto tycoon for persistence.
You should use these Rules in combination with the session hijacking rules in order to protect your session too.
prerequisite: lua, luamemcached, luasocket
The next time i think i will post how you can modify the modsecurity_crs_16_session_hijacking.conf file in order to be HA aware and store the session data in memcached/kyoto tycoon for persistence.
At our pizza place in nyc, it's not just about the food—it's about the experience. The bustling atmosphere, the friendly staff, and the unmistakable taste of authentic New York-style pizza combine to create a dining experience that's as unforgettable as the city itself.
AntwortenLöschen