Project

General

Profile

Support #3287 » web_http_audit_demo.lua

lua script - xu hui, 11/08/2019 08:46 AM

 
json = require "cjson.safe"
md5 = require "md5"

-- log_info
app_type = "web"
event_type = "lua"
event_name = "http"
name = "web_http_audit.json"

-- web_info
login_url = "/login"
success_code = 0

-- common_mapping
http_common_mapping = '{"accept":"accept","accept-charset":"accept_charset","accept-encoding":"accept_encoding","accept-language":"accept_language","accept-datetime":"accept_datetime","authorization":"authorization","cache-control":"cache_control","from":"from","max-forwards":"max_forwards","origin":"origin","pragma":"pragma","proxy-authorization":"proxy_authorization","via":"via","vary":"vary","x-requested-with":"x_requested_with","x-forwarded-proto":"x_forwarded_proto","accept-range":"accept_range","allow":"allow","connection":"connection","content-encoding":"content_encoding","content-language":"content_language","content-location":"content_location","content-md5":"content_md5","content-range":"content_range","date":"date","last-modified":"last_modified","location":"location","proxy-authenticate":"proxy_authenticate","referrer":"refer","retry-after":"retry_after","server":"server","transfer-encoding":"transfer_encoding","upgrade":"upgrade","www-authenticate":"www_authenticate","x-authenticated-user":"x_authenticated_user","x-forwarded-for":"xff","x-real-ip":"x_real_ip"}'
common_mapping_table = json.decode(http_common_mapping)

-- request_mapping
http_request_mapping = '{"content-length":"request_content_length","content-type":"request_content_type","appversion":"app_version","usercountry":"user_country","localcountry":"local_country","device":"device","devtype":"device_type","deviceid":"device_id","canvas":"canvas","webgl":"webgl","x-ftoken":"x-ftoken"}'

request_mapping_table = json.decode(http_request_mapping)

-- response_mapping
http_response_mapping = '{"content-length":"response_content_length","content-type":"response_content_type"}'
response_mapping_table = json.decode(http_response_mapping)

-- bypass_host
bypass_host = {
"www.test1.com",
"www.test2.com"
}

-- bypass_url
bypass_url = {
"/bypass_1.html",
"/bypass_2.html"
}

-- bypass_ua
bypass_ua = {
"Cloudflare-Traffic-Manager"
}

-- request_session_id_pattern
session_id_pattern = {
"sessionID-1_=(.-);",
"sessionID-2_=(.-);"
}

-- defind function
function md5Encode(args)
m = md5.new()
m:update(args)
return md5.tohex(m:finish())
end

function urlDecode(args)
s = string.gsub(args, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
return s
end

function string.split(s, p)
rt = {}
string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end )
return rt
end

function string.trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end

function formatBody(args)
t = {}
data = string.split(args, '&')
for n, v in ipairs(data) do
d = string.split(v, '=')
t[d[1]] = d[2]
end
return t
end


-- default funtion
function init(args)
local needs = {}
needs["protocol"] = "http"
return needs
end

function setup(args)
filename = SCLogPath() .. "/" .. name
file = assert(io.open(filename, "a"))
SCLogInfo("web_http_audit filename: " .. filename)
http = 0
end

function log(args)

-- init tables
http_table = {}

http_hostname = HttpGetRequestHost()
if http_hostname then
if string.match(http_hostname, "test1") == nil and string.match(http_hostname, "test2") == nil then
return
end
for _, host in ipairs(bypass_host) do
if http_hostname == host then
return
end
end
end
http_table["hostname"] = http_hostname

http_ua = HttpGetRequestHeader("User-Agent")
if http_ua then
for _, ua in ipairs(bypass_ua) do
if string.match(http_ua, ua) then
return
end
end
end
http_table["user_agent"] = http_ua

http_url = HttpGetRequestUriNormalized()
for _, url in ipairs(bypass_url) do
if url == http_url then
return
end
end
http_table["url"] = http_url

if http_url then
http_url_path = string.split(http_url, "?")[1]
http_table["url_path"] = http_url_path
end

rl = HttpGetRequestLine()
if rl then
http_method = string.match(rl, "%w+")
http_table["method"] = http_method
end

rsl = HttpGetResponseLine()
if rsl then
status_code = string.match(rsl, "%s(%d+)%s")
http_table["status"] = tonumber(status_code)

http_protocol = string.match(rsl, "(.-)%s")
http_table["protocol"] = http_protocol
end

cookie = HttpGetRequestHeader("Cookie")
http_table["cookie"] = cookie

set_cookie = HttpGetResponseHeader("Set-Cookie")
http_table["set_cookie"] = set_cookie

---[[
if cookie then
--[[
-- request_token
for _, pattern in ipairs(session_id_pattern) do
session_id = string.match(cookie, pattern)
if session_id then
http_table["token"] = md5Encode(session_id)
break
end
end
--]]

-- request_member_id
request_member_id = string.match(cookie, "memberId=(.-);")
if request_member_id then
http_table["member_id"] = tonumber(request_member_id)
end

-- email
userinfo_email = string.match(cookie, "userinfo_email=(.-);")
if userinfo_email then
http_table["email"] = urlDecode(userinfo_email)
end
end

if set_cookie then
-- response_token
--[[
for _, pattern in ipairs(session_id_pattern) do
session_id = string.match(set_cookie, pattern)
if session_id then
http_table["token"] = md5Encode(session_id)
break
end
end
--]]
-- response_member_id
response_member_id = string.match(set_cookie, "memberId=(.-);")
if response_member_id then
http_table["member_id"] = tonumber(response_member_id)
end

-- userinfo_email
userinfo_email = string.match(set_cookie, "userinfo_email=(.-);")
if userinfo_email then
http_table["email"] = urlDecode(userinfo_email)
end
end

--]]

-- login_audit
if http_url == login_url and http_method == "POST" then
-- token && member_id
if set_cookie then
session_id = string.match(set_cookie, "sessionID=(.-);")
if session_id then
http_table["token"] = md5Encode(session_id)
member_id = string.match(set_cookie, "memberId=(.-);")
if member_id then
http_table["member_id"] = tonumber(member_id)
end
end
end

-- login_results
a, o, e = HttpGetResponseBody()
if a then
for n, v in ipairs(a) do
body = json.decode(v)
results_code = tonumber(body["code"])
if results_code == success_code then
results = "success"
else
results = "failed"
end
end
http_table["results"] = results
http_table["results_code"] = results_code
end

-- login_email
a, o, e = HttpGetRequestBody()
if a then
for n, v in ipairs(a) do
res = formatBody(v)
if res['email'] then
http_table["email"] = urlDecode(res['email'])
break
end
end
end
end

-- RequestHeaders
rh = HttpGetRequestHeaders()
if rh then
for k, v in pairs(rh) do
key = string.lower(k)

common_var = common_mapping_table[key]
if common_var then
http_table[common_var] = v
end

request_var = request_mapping_table[key]
if request_var then
http_table[request_var] = v
end
end
end

-- ResponseHeaders
rsh = HttpGetResponseHeaders()
if rsh then
for k, v in pairs(rsh) do
key = string.lower(k)
common_var = common_mapping_table[key]
if common_var then
http_table[common_var] = v
end
response_var = response_mapping_table[key]
if response_var then
http_table[response_var] = v
end
end
end


-- timestring = SCPacketTimeString() 2019-09-10T06:08:35.582449+0000
sec, usec = SCPacketTimestamp()
timestring = os.date("!%Y-%m-%dT%T", sec) .. '.' .. usec .. '+0000'
-- flow_info
ip_version, src_ip, dst_ip, protocol, src_port, dst_port = SCFlowTuple()

-- flow_id
id = SCFlowId()
flow_id = string.format("%.0f", id)
flow_id = tonumber(flow_id)

-- alerts
has_alerts = SCFlowHasAlerts()

-- true_client_ip
true_client_ip = HttpGetRequestHeader("True-Client-IP")
if true_client_ip then
http_table["proxy_ip"] = src_ip
http_table["true_client_ip"] = true_client_ip
src_ip = true_client_ip
end

-- session_id
tetrad = src_ip .. src_port .. dst_ip .. dst_port
session_id = md5Encode(tetrad)

-- table
raw_data = {
timestamp = timestring,
flow_id = flow_id,
session_id = session_id,
src_ip = src_ip,
src_port = src_port,
proto = "TCP",
dest_ip = dst_ip,
dest_port = dst_port,
event_name = event_name,
event_type = event_type,
app_type = app_type,
http = http_table,
alerted = has_alerts
}

-- json encode
data = json.encode(raw_data)

-- write_data
file:write(data .. "\n")
file:flush()

http = http + 1
end

function deinit (args)
SCLogInfo ("web_http_audit transactions logged: " .. http);
file:close(file)
end
(3-3/3)