16.2. Lua函数¶
16.2.1. 小包裹¶
初始化方式:
function init (args)
local needs = {}
needs["type"] = "packet"
return needs
end
16.2.1.1. SCPacketTimestamp¶
以2个数字获取数据包时间戳:从1970-01-01 00:00:00 UTC开始经过的秒和微秒。
function log(args)
local sec, usec = SCPacketTimestamp()
end
16.2.1.2. SCPacketTimeString¶
使用 SCPacketTimeString
获取数据包的时间字符串格式为:11/24/2009-18:57:25.179869
function log(args)
ts = SCPacketTimeString()
16.2.1.3. SCPacketTuple¶
ipver, srcip, dstip, proto, sp, dp = SCPacketTuple()
16.2.1.4. SCPacketPayload¶
p = SCPacketPayload()
16.2.2. 流¶
function init (args)
local needs = {}
needs["type"] = "flow"
return needs
end
16.2.2.1. SCFlowTimestamps¶
从流中获取第一个和最后一个数据包的时间戳(秒和微秒)。
startts, lastts = SCFlowTimestamps()
startts_s, lastts_s, startts_us, lastts_us = SCFlowTimestamps()
16.2.2.2. SCFlowTimeString¶
startts = SCFlowTimeString()
16.2.2.3. SCFlowTuple¶
ipver, srcip, dstip, proto, sp, dp = SCFlowTuple()
16.2.2.4. SCFlowAppLayerProto¶
从水流中得到一根绳子。如果一个alproto未知,它返回“unknown”。
例子:
function log(args)
alproto = SCFlowAppLayerProto()
if alproto ~= nil then
print (alproto)
end
end
返回5个值:<alproto><alproto-ts><alproto-tc><alproto-orig><alproto-expect>
在更改和升级协议时使用orig和expect。在smtp starttls情况下,orig通常设置为“smtp”,并期望设置为“tls”。
16.2.2.5. SCFlowHasAlerts¶
如果流有警报,则返回true。
例子:
function log(args)
has_alerts = SCFlowHasAlerts()
if has_alerts then
-- do something
end
end
16.2.2.6. SCFlowStats¶
获取每个流的数据包和字节计数。
tscnt, tsbytes, tccnt, tcbytes = SCFlowStats()
16.2.2.7. SCFlowId¶
获取流ID。
id = SCFlowId()
请注意,简单地打印“id”可能会导致打印科学符号。要避免这种情况,只需:
id = SCFlowId()
idstr = string.format("%.0f",id)
print ("Flow ID: " .. idstr .. "\n")
16.2.3. HTTP协议¶
初始化方式:
function init (args)
local needs = {}
needs["protocol"] = "http"
return needs
end
16.2.3.1. httpGetRequestBody和httpGetResponseBody。¶
通过httpGetRequestBody和httpGetResponseBody使规范化的正文数据可用于脚本。
不能保证所有的尸体都可以使用。
例子:
function log(args)
a, o, e = HttpGetResponseBody();
--print("offset " .. o .. " end " .. e)
for n, v in ipairs(a) do
print(v)
end
end
16.2.3.2. HttpGetRequestHost¶
从libhtp的tx->request_hostname获取主机,hostname可以是URL的主机部分,也可以是主机头的主机部分。
例子:
http_host = HttpGetRequestHost()
if http_host == nil then
http_host = "<hostname unknown>"
end
16.2.3.3. HttpGetRequestHeader¶
http_ua = HttpGetRequestHeader("User-Agent")
if http_ua == nil then
http_ua = "<useragent unknown>"
end
16.2.3.4. HttpGetResponseHeader¶
server = HttpGetResponseHeader("Server");
print ("Server: " .. server);
16.2.3.5. HttpGetRequestLine¶
rl = HttpGetRequestLine();
print ("Request Line: " .. rl);
16.2.3.6. HttpGetResponseLine¶
rsl = HttpGetResponseLine();
print ("Response Line: " .. rsl);
16.2.3.7. HttpGetRawRequestHeaders¶
rh = HttpGetRawRequestHeaders();
print ("Raw Request Headers: " .. rh);
16.2.3.8. HttpGetRawResponseHeaders¶
rh = HttpGetRawResponseHeaders();
print ("Raw Response Headers: " .. rh);
16.2.3.9. HttpGetRequestUriRaw¶
http_uri = HttpGetRequestUriRaw()
if http_uri == nil then
http_uri = "<unknown>"
end
16.2.3.10. HttpGetRequestUriNormalized¶
http_uri = HttpGetRequestUriNormalized()
if http_uri == nil then
http_uri = "<unknown>"
end
16.2.3.11. HttpGetRequestHeaders¶
a = HttpGetRequestHeaders();
for n, v in pairs(a) do
print(n,v)
end
16.2.3.12. HttpGetResponseHeaders¶
a = HttpGetResponseHeaders();
for n, v in pairs(a) do
print(n,v)
end
16.2.4. DNS¶
16.2.4.1. DnsGetQueries¶
dns_query = DnsGetQueries();
if dns_query ~= nil then
for n, t in pairs(dns_query) do
rrname = t["rrname"]
rrtype = t["type"]
print ("QUERY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
"TODO" .. " [**] " .. srcip .. ":" .. sp .. " -> " ..
dstip .. ":" .. dp)
end
end
返回表的表
16.2.4.2. DnsGetAnswers¶
dns_answers = DnsGetAnswers();
if dns_answers ~= nil then
for n, t in pairs(dns_answers) do
rrname = t["rrname"]
rrtype = t["type"]
ttl = t["ttl"]
print ("ANSWER: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
ttl .. " [**] " .. srcip .. ":" .. sp .. " -> " ..
dstip .. ":" .. dp)
end
end
返回表的表
16.2.4.4. DnsGetRcode¶
rcode = DnsGetRcode();
if rcode == nil then
return 0
end
print (rcode)
返回一个带有错误消息的Lua字符串,或为零
16.2.4.5. DnsGetRecursionDesired¶
if DnsGetRecursionDesired() == true then
print ("RECURSION DESIRED")
end
返回bool
16.2.5. TLS¶
初始化方式:
function init (args)
local needs = {}
needs["protocol"] = "tls"
return needs
end
16.2.5.1. TlsGetVersion¶
通过tls get version以字符串形式获取TLS会话中协商的版本。
例子:
function log (args)
version = TlsGetVersion()
if version then
-- do something
end
end
16.2.5.2. TlsGetCertInfo¶
通过tlsgetcertinfo使证书信息可用于脚本。
例子:
function log (args)
version, subject, issuer, fingerprint = TlsGetCertInfo()
if version == nil then
return 0
end
end
16.2.5.3. TlsGetCertChain¶
通过tlsgetcertchain使证书链对脚本可用。
输出是一个证书数组,每个证书都是哈希 data 和 length 钥匙。
例子:
-- Use debian lua-luaossl coming from https://github.com/wahern/luaossl
local x509 = require"openssl.x509"
chain = TlsGetCertChain()
for k, v in pairs(chain) do
-- v.length is length of data
-- v.data is raw binary data of certificate
cert = x509.new(v["data"], "DER")
print(cert:text() .. "\n")
end
16.2.5.4. TlsGetCertNotAfter¶
获取证书有效期结束的Unix时间戳。
例子:
function log (args)
notafter = TlsGetCertNotAfter()
if notafter < os.time() then
-- expired certificate
end
end
16.2.5.5. TlsGetCertNotBefore¶
获取证书有效期开始的Unix时间戳。
例子:
function log (args)
notbefore = TlsGetCertNotBefore()
if notbefore > os.time() then
-- not yet valid certificate
end
end
16.2.5.6. TlsGetCertSerial¶
通过tlsgetcertserial获取TLS证书序列号。
例子:
function log (args)
serial = TlsGetCertSerial()
if serial then
-- do something
end
end
16.2.5.7. TLSGetsni公司¶
从TLS连接获取服务器名称指示。
例子:
function log (args)
asked_domain = TlsGetSNI()
if string.find(asked_domain, "badguys") then
-- ok connection to bad guys let's do someting
end
end
16.2.6. 日本3¶
必须在suricata配置文件中启用JA3(将“app layer.protocols.tls.ja3 fingerprints”设置为“yes”)。
初始化方式:
function init (args)
local needs = {}
needs["protocol"] = "tls"
return needs
end
16.2.6.1. JA3GETHASH公司¶
通过ja3 get hash获取ja3散列(ja3字符串的md5sum)。
例子:
function log (args)
hash = Ja3GetHash()
if hash == nil then
return
end
end
16.2.6.2. JA3字符串¶
通过ja3 get string获取ja3字符串。
例子:
function log (args)
str = Ja3GetString()
if str == nil then
return
end
end
16.2.6.3. JA3获取哈希¶
通过ja3s get hash获取ja3s散列(ja3s字符串的md5sum)。
例子:
function log (args)
hash = Ja3SGetHash()
if hash == nil then
return
end
end
16.2.6.4. JA3获取字符串¶
通过ja3sGetString获取ja3s字符串。
例子:
function log (args)
str = Ja3SGetString()
if str == nil then
return
end
end
16.2.7. SSH¶
初始化方式:
function init (args)
local needs = {}
needs["protocol"] = "ssh"
return needs
end
16.2.7.1. SshGetServerProtoVersion¶
通过sshgetserverprotoversion获取服务器使用的ssh协议版本。
例子:
function log (args)
version = SshGetServerProtoVersion()
if version == nil then
return 0
end
end
16.2.7.2. SshGetServerSoftwareVersion¶
通过sshgetserversoftwareversion获取服务器使用的ssh软件。
例子:
function log (args)
software = SshGetServerSoftwareVersion()
if software == nil then
return 0
end
end
16.2.7.3. SshGetClientProtoVersion¶
通过sshgetclientProtoversion获取客户端使用的ssh协议版本。
例子:
function log (args)
version = SshGetClientProtoVersion()
if version == nil then
return 0
end
end
16.2.7.4. SshGetClientSoftwareVersion¶
通过sshgetclientsoftwareversion获取客户端使用的ssh软件。
例子:
function log (args)
software = SshGetClientSoftwareVersion()
if software == nil then
return 0
end
end
16.2.7.5. HasshGet¶
通过hassget获取客户端使用的hash算法的MD5。
例子:
function log (args)
hassh = HasshGet()
if hassh == nil then
return 0
end
end
16.2.7.6. HasshGetString¶
通过HasshGetString获取客户端使用的hash算法。
例子:
function log (args)
hassh_string = HasshGetString()
if hassh == nil then
return 0
end
end
16.2.7.7. HasshServerGet¶
通过HasshServerGet获取服务器使用的hash算法的MD5。
例子:
function log (args)
hassh_string = HasshServerGet()
if hassh == nil then
return 0
end
end
16.2.7.8. HasshServerGetString¶
通过hassServerGetString获取服务器使用的hash算法。
例子:
function log (args)
hassh_string = HasshServerGetString()
if hassh == nil then
return 0
end
end
16.2.8. 文件夹¶
要使用文件日志API,脚本的init()函数需要如下所示:
function init (args)
local needs = {}
needs['type'] = 'file'
return needs
end
16.2.8.1. SCFileInfo¶
fileid, txid, name, size, magic, md5, sha1, sha256 = SCFileInfo()
返回祸不单行中的fileID(Number),txid(Number),name(String),size(Number),magic(String),md5(String),sha1(String),sha256(String)
16.2.8.2. SCFileState¶
state, stored = SCFileState()
返回状态(字符串),存储(bool)
16.2.9. 警报¶
警报是“数据包”记录器的一个子集:
function init (args)
local needs = {}
needs["type"] = "packet"
needs["filter"] = "alerts"
return needs
end
16.2.9.1. SCRuleIds¶
sid, rev, gid = SCRuleIds()
16.2.9.2. SCRuleAction¶
action = SCRuleAction()
返回“PASS”、“REJECT”、“DROP”或“ALERT”之一
16.2.9.3. SCRuleMsg¶
msg = SCRuleMsg()
16.2.9.4. SCRuleClass¶
class, prio = SCRuleClass()
16.2.10. 流式数据¶
流数据当前可以注销重新组装的TCP数据和规范化的HTTP数据。将为每个连续的数据块调用该脚本。
在TCP重新组装数据的情况下,所有可能的重叠都会根据主机OS设置删除。
function init (args)
local needs = {}
needs["type"] = "streaming"
needs["filter"] = "tcp"
return needs
end
在HTTP主体数据的情况下,如果适用,主体将被解压和卸载。
function init (args)
local needs = {}
needs["type"] = "streaming"
needs["protocol"] = "http"
return needs
end
16.2.10.1. SCStreamingBuffer¶
function log(args)
data = SCStreamingBuffer()
hex_dump(data)
end
16.2.11. 流量变量¶
可以从Lua访问、定义和修改流变量。为此,必须使用本节中描述的函数并在init函数中声明计数器:
function init(args)
local needs = {}
needs["tls"] tostring(true)
needs["flowint"] = {"tls-cnt"}
return needs
end
这里我们定义一个 tls-cnt 现在可以通过专用函数在输出或签名中使用的Flowint。对Flow变量的访问是通过索引完成的,因此在我们的例子中,我们需要使用0。
function match(args)
a = SCFlowintGet(0);
if a then
SCFlowintSet(0, a + 1)
else
SCFlowintSet(0, 1)
end
16.2.11.1. SCFlowintGet¶
获取参数给定的索引处的flowInt。
16.2.11.2. SCFlowintSet¶
在第一个参数给出的索引处设置flowInt。第二个参数是值。
16.2.11.3. SCFlowintIncr¶
在第一个参数给出的索引处增加flowInt。
16.2.11.4. SCFlowintDecr¶
在第一个参数给出的索引处减少FlowInt。
16.2.11.5. SCFlowvarGet¶
获取参数给定的索引处的flowvar。
16.2.11.6. SCFlowvarSet¶
设置flowvar。第一个参数是索引,第二个参数是数据,第三个参数是数据长度。
你可以用它来设置字符串
function init (args)
local needs = {}
needs["http.request_headers"] = tostring(true)
needs["flowvar"] = {"cnt"}
return needs
end
function match(args)
a = SCFlowvarGet(0);
if a then
a = tostring(tonumber(a)+1)
SCFlowvarSet(0, a, #a)
else
a = tostring(1)
SCFlowvarSet(0, a, #a)
end
16.2.12. 误码率¶
16.2.12.1. SCThreadInfo¶
tid, tname, tgroup = SCThreadInfo()
它给出:tid(整数)、tname(字符串)、tgroup(字符串)
16.2.12.2. SClogError、SClogWarning、SClogNotice、SCloginfo、SClogDebug¶
打印消息。它将进入yaml中定义的输出。是否打印取决于日志级别。
例子:
SCLogError("some error message")
16.2.12.3. SCLogPath¶
公开日志路径。
name = "fast_lua.log"
function setup (args)
filename = SCLogPath() .. "/" .. name
file = assert(io.open(filename, "a"))
end