lua 支持

2019-07-05  本文已影响0人  lx_jian

1. Lua在Suricata中的使用

Lua脚本可以在Suricata的两个组件中使用。第一个是在输出。第二个是检测引擎的规则中。

这个两个功能都使用一系列函数来访问Suricata提取的数据。您可以在Lua函数页面中获取函数列表。

1.1 Lua 输出

Lua可以用来写任意输出。有关更多信息,请参阅Lua输出

1.2 Lua检测

Lua脚本可以用作规则中的过滤条件。有关更多信息,请查看下面的Lua函数

2. Lua函数

2.1 packet

初始化为:

function  init(args)

        localneeds={}

        needs["type"]="packet"

        return needs

end

2.1.1 SCPacketTimestamp

获取数据包时间戳为2个数字:自1970-01-01 00:00:00 UTC以来经过的秒数和微秒数.

function  log(args)

      localsec,usec=SCPacketTimestamp()

end

2.1.2  SCPacketTimeString

添加SCPacketTimeString以获取数据包时间字符串的格式为:11/24 / 2009-18:57:25.179869

function log(args)

      ts=SCPacketTimeString()

end

2.1.3 SCPacketTuple

ipver,srcip,dstip,proto,sp,dp=SCPacketTuple()

2.1.4 SCPacketPayload 

p = SCPacketPayload()

2.2 flow

function  init(args)

        localneeds={}

        needs["type"]="flow"

        return needs

end

2.2.1. SCFlowTimestamps

获取流中第一个和最后一个数据包的时间戳(秒和微秒)

startts,lastts=SCFlowTimestamps()

startts_s,lastts_s,startts_us,lastts_us=SCFlowTimestamps()

2.2.2. SCFlowTimeString

startts=SCFlowTimeString()

2.2.3. SCFlowTuple

ipver,srcip,dstip,proto,sp,dp=SCFlowTuple()

2.2.4. SCFlowAppLayerProto

从流程中获取alprotos作为字符串。如果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”。

2.2.5. SCFlowHasAlerts

如果流有警报,则返回true。

如:

function  log(args)

        has_alerts=SCFlowHasAlerts()

        if has_alerts then

            --do something

        end

end

2.2.6. SCFlowStats

获取每个流的数据包和字节数。

tscnt,tsbytes,tccnt,tcbytes=SCFlowStats()

2.2.7. SCFlowId

获取流ID

id=SCFlowId()

请注意,简单地打印“id”可能会导致打印科学记数法。为避免这种情况,只需:

id=SCFlowId()

idstr=string.format("%.0f",id)

print("Flow ID: "..idstr.."\n")

2.3 HTTP

初始化

function  init(args)

        localneeds={}

        needs["protocol"]="http"

        return needs

end

2.3.1 HttpGetRequestBody和HttpGetResponseBody

通过HttpGetRequestBody和HttpGetResponseBody为脚本提供标准化的正文数据。

无法保证所有身体都可以使用.

如:

function  log(args)

        a,o,e=HttpGetResponseBody();

        --print("offset "..o.." end "..e)

        for n,vinipairs(a) do

                print(v)

        end

end

2.3.2 HttpGetRequestHost

从libhtp的tx-> request_hostname获取主机,它可以是url的主机部分,也可以是Host头的主机部分。

如:

http_host = HttpGetRequestHost()

if http_host==nil then

    http_host="<hostname unknown>"

end

2.3.3 HttpGetRequestHeader 

http_ua = HttpGetRequestHeader("User-Agent")

if  http_ua==nil then

        http_ua="<useragent unknown>"

end

2.3.4 HttpGetResponseHeader

server=HttpGetResponseHeader("Server");

print("Server: "..server);

2.3.5 HttpGetRequestLine

rl=HttpGetRequestLine();

print("Request Line: "..rl);

2.3.6 HttpGetResponseLine

rsl=HttpGetResponseLine();

print("Response Line: "..rsl);

2.3.7 HttpGetRawRequestHeaders

rh=HttpGetRawRequestHeaders();

print("Raw Request Headers: "..rh);

2.3.8 HttpGetRawResponseHeaders 

rh=HttpGetRawResponseHeaders();

print("Raw Response Headers: "..rh);

2.3.9 HttpGetRequestUriRaw

http_uri=HttpGetRequestUriRaw()

if http_uri==nil then

        http_uri="<unknown>"

end

2.3.10 HttpGetRequestUriNormalized

http_uri =HttpGetRequestUriNormalized() 

if http_uri==nilthen

    http_uri="<unknown>"

end

2.3.11 HttpGetRequestHeaders

a=HttpGetRequestHeaders();

for n,vinpairs(a) do 

    print(n,v)

end

2.3.12 HttpGetResponseHeaders

a=HttpGetResponseHeaders();

for n,vinpairs(a) do

    print(n,v)

end

2.4 DNS 

2.4.1 DnsGetQueries 

dns_query=DnsGetQueries();

if dns_query~=nil then

        for n,tinpairs(dns_query) do

                rrname=t["rrname"]

                rrtype=t["type"]

                print("QUERY: "..ts.." "..rrname.." [**] "..rrtype.." [**] ".."TODO".." [**] "..srcip..":"..sp.." -> "..dstip..":"..dp)

        end

end

返回一个表格的表

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

返回一个表格的表

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

返回一个表格的表

2.4.4 DnsGetRcode 

rcode = DnsGetRcode();

if rcode == nil then

    return 0

end

print (rcode)

返回带有错误消息的lua字符串,或者为nil

2.4.5 DnsGetRecursionDesired 

if  DnsGetRecursionDesired()==true then

        print("RECURSION DESIRED")

end

2.5 TLS 

初始化为:

function init (args)

    local needs = {}

    needs["protocol"] = "tls"

    return needs

end

2.5.1 TlsGetVersion 

通过TlsGetVersion将TLS会话中的协商版本作为字符串获取。

如:

function log(args)

    version=TlsGetVersion()

    if version then

        -- do something

    end

end

2.5.2 TlsGetCertInfo 

通过TlsGetCertInfo为脚本提供证书信息。

如:

function log (args)

    version, subject, issuer, fingerprint = TlsGetCertInfo()

    if version == nil then

        return 0

    end

end

2.5.3 TlsGetCertChain

通过TlsGetCertChain使证书链可用于脚本。

输出是一个证书数组,每个证书都是带有数据和长度密钥的哈希。

如:

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

2.5.4 TlsGetCertNotAfter 

获取证书有效期结束的Unix时间戳。

function log (args)

    notafter = TlsGetCertNotAfter()

    if notafter < os.time() then

        -- expired certificate

    end

end

2.5.5 TlsGetCertNotBefore 

获取证书有效期开始的Unix时间戳。

如:

function log (args)

    notbefore = TlsGetCertNotBefore()

    if notbefore > os.time() then

        -- not yet valid certificate

    end

end

2.5.6 TlsGetCertSerial 

通过TlsGetCertSerial获取TLS证书序列号。

如:

function log (args)

    serial = TlsGetCertSerial()

    if serial then

        -- do something

    end

end

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

2.6 JA3

必须在Suricata配置文件中启用JA3(将'app-layer.protocols.tls.ja3-fingerprints'设置为'yes')。

初始化为:

function init (args)

    local needs = {}

    needs["protocol"] = "tls"

    return needs

end

2.6.1 Ja3GetHash 

通过Ja3GetHash获取JA3哈希(JA3字符串的md5sum)。

如:

function log (args)

    hash = Ja3GetHash()

    if hash == nil then

        return

    end

end

2.6.2 Ja3GetString

通过Ja3GetString获取JA3字符串。

如:

function log (args)

    str = Ja3GetString()

    if str == nil then

        return

    end

end

2.7 SSH

初始为:

function init (args)

    local needs = {}

    needs["protocol"] = "ssh"

    return needs

end

2.7.1 SshGetServerProtoVersion

通过SshGetServerProtoVersion获取服务器使用的SSH协议版本。

如:

function log (args)

    version = SshGetServerProtoVersion()

    if version == nil then

        return 0

    end

end

2.7.2 SshGetServerSoftwareVersion

通过SshGetServerSoftwareVersion获取服务器使用的SSH软件。

如:

function log (args)

    software = SshGetServerSoftwareVersion()

    if software == nil then

        return 0

    end

end

2.7.3 SshGetClientProtoVersion

通过SshGetClientProtoVersion获取客户端使用的SSH协议版本。

如:

function log (args)

    version = SshGetClientProtoVersion()

    if version == nil then

        return 0

    end

end

2.7.4 SshGetClientSoftwareVersion

通过SshGetClientSoftwareVersion获取客户端使用的SSH软件。

如:

function log (args)

    software = SshGetClientSoftwareVersion()

    if software == nil then

        return 0

    end

end

2.8 Files

要使用文件记录API,脚本的init()函数需要如下所示:

function init (args)

    local needs = {}

    needs['type'] = 'file'

    return needs

end

2.8.1 SCFileInfo

fileid,txid,name,size,magic,md5=SCFileInfo()

返回fileid(数字),txid(数字),名称(字符串),大小(数字),magic(字符串),md5(十六进制)(字符串)

2.8.2 SCFileState

state,stored=SCFileState()

返回状态(字符串),存储(bool)

2.9  Alerts

警报是“packet”记录器的子集:

function init (args)

    local needs = {}

    needs["type"] = "packet"

    needs["filter"] = "alerts"

    return needs

end

2.9.1 SCRuleIds

sid,rev,gid=SCRuleIds()

2.9.2 SCRuleMsg

msg=SCRuleMsg()

2.9.3 SCRuleClass

class,prio=SCRuleClass()

2.10Streaming Data

流数据当前可以注销重组的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

2.10.1 SCStreamingBuffer

function log(args)

    data = SCStreamingBuffer()

    hex_dump(data)

end

2.11 Flow variables

可以从Lua访问,定义和修改Flow变量。为此,您必须使用本节中描述的函数并在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

2.11.1 ScFlowintGet

获取Flowint在参数给定的索引处

2.11.2 ScFlowintSet

将Flowint设置为第一个参数给定的索引。第二个参数是值。

2.11.3 ScFlowintIncr

在第一个参数给出的索引处递增Flowint。

2.11.4 ScFlowintDecr

在第一个参数给出的索引处减少Flowint。

2.11.5 ScFlowvarGet

获取参数给定的索引处的Flowvar。

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

2.12 Misc

2.12.1 SCThreadInfo

tid,tname,tgroup=SCThreadInfo()

它给出:tid(整数),tname(字符串),tgroup(字符串)

2.12.2 SCLogError, SCLogWarning, SCLogNotice, SCLogInfo, SCLogDebug

打印一条消息。它将进入yaml中定义的输出。是否打印取决于日志级别。

如:

SCLogError("some error message")

2.12.3 SCLogPath

公开日志路径

name = "fast_lua.log"

function setup (args)

    filename = SCLogPath() .. "/" .. name

    file = assert(io.open(filename, "a"))

end

上一篇下一篇

猜你喜欢

热点阅读