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.3. DnsGetAuthorities

dns_auth = DnsGetAuthorities();
if dns_auth ~= nil then
    for n, t in pairs(dns_auth) do
        rrname = t["rrname"]
        rrtype = t["type"]
        ttl = t["ttl"]

        print ("AUTHORITY: " .. 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使证书链对脚本可用。

输出是一个证书数组,每个证书都是哈希 datalength 钥匙。

例子:

-- 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