Skip to content

Instantly share code, notes, and snippets.

@norandom
Created December 14, 2015 11:35
Show Gist options
  • Save norandom/f3d5006b858c77810e63 to your computer and use it in GitHub Desktop.
Save norandom/f3d5006b858c77810e63 to your computer and use it in GitHub Desktop.
suricata 2.0.10 URL comparer
-- url comparision Lua script for suricata
-- author: marius - at - because-security.com
-- rule:
-- # Compare URLs with a black list
-- alert tcp any any -> any any (msg:"CUSTOM BAD url"; luajit:bad_urls.lua; sid:1;)
-- file:
-- some folder: bad_urls.txt:
-- http:/foo.bar/malware.exe
-- http://www.blala/malware123.exe
-- this gets called during rule parsing
function init (args)
local needs = {}
needs["payload"] = tostring(true)
return needs
end
-- this gets executed one time once per thread at init
-- read urls from file and keep them in a table
local url_file = io.open("/etc/suricata/rules/bad_urls.txt", "r");
arr = {}
for line in url_file:lines() do
table.insert (arr, line);
end
url_file:close()
-- define our protocol methods
http_methods = { "GET", "POST", "PUT", "OPTIONS" }
-- this is a matcher function
function match(args)
a = tostring(args["payload"])
if #a > 0 then
-- primitive protocol detection on ASCII
local file = io.open("/var/log/suricata/bad_urls_dbg.log", "a")
local http_method = string.match(a, '^([%l%u]+)%s+')
for _, v in ipairs(http_methods) do
if v == http_method then
http = true
file:write("http: " .. "yes" .. "\n")
file:flush()
end
end
if http then
local http_request = split(a, "\r?\n")
if http_request[1] and http_request[2] then
uri = string.match(http_request[1], "^GET%s+(.+)%sHTTP")
host = string.match(http_request[2], "^Host:%s+(.+)")
file:flush()
end
if uri and host then
url = host .. uri
file:write("url: " .. url .. "\n")
file:flush()
end
if url and uri and host then
local verbose = true
if verbose then
-- file:write("http req: " .. http_request[1] .. "\n")
file:write("uri: " .. uri .. "\n")
file:write("host: " .. host .. "\n")
file:write("url: " .. "http://" .. url .. "\n")
file:flush()
end
for _, v in ipairs(arr) do
if v:find(host .. uri) then
file:write("BAD URL match " .. host .. uri .. " vs " .. v .. "\n")
file:flush()
file:close()
return 1
end
end
end
file:flush()
file:close()
end
end
return 0
end
-- split function to get http requests line by line
function split(str, delim)
local result,pat,lastPos = {},"(.-)" .. delim .. "()",1
for part, pos in string.gfind(str, pat) do
table.insert(result, part); lastPos = pos
end
table.insert(result, string.sub(str, lastPos))
return result
end
return 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment