Using packet buffer in Lua

I’m writing a lua script for a rule (not output). Is there a way to get the full packet from lua? If I try something, for example, like this:

function init (args)
    local needs = {}
    needs["packet"] = tostring(true)
    return needs
end

function match(args)
    p = args["packet"]
    SCLogNotice(p)
    return 1
end

Nothing is output to suricata.log. Is there a way to just get the whole packet in hexadecimal characters? What am I missing?

Hi Joseph,

From the documentation, I’m not sure there’s something just like that.

You could use SCPacketPayload to get access to the packet contents, and SCPacketTuple to access IP version, and source and destination IP and ports.

Another thing that may be causing issues is the way you’re retrieving the packet in your init function. According to documentation, and from my own experience, it should be: needs["type"] = "packet".

Not sure if that’s another possible way, but maybe that could also help in moving forward with your intent!

Source of what I’ve mentioned:
https://suricata.readthedocs.io/en/suricata-6.0.3/lua/lua-functions.html#packet

well basically the hope was that I could get the IP and the http URI at the same time with the packet, which isn’t really easy without those things.

You could retrieve those data and format a string with the information you want with string.format() Would that help?

Well as far as I know you can’t retrieve that data at the same time because they’re in different buffers. maybe that’s a better question – can you get the source ip and http uri at the same time?

Maybe this script from one of our Suricata-Verify tests for lua output could help in understanding the possibilities on that sense?

Edit: sorry, had linked to my personal repo. fixed.

Thank you. But don;t you have to define a buffer with writing lua scripts for detection? 6.34. Lua Scripting — Suricata 6.0.0 documentation

Hm, I think there may be some more freedom as to how you write things within the match function in the lua script.

Check this other Suricata-verify test:

As for a buffer, if you want that, I could be wrong, but I think you could build your own, using string.format(). Then you format it the way it would show up in the packet. S-V test for DNS output in lua has an example of formatting a string:

I’m not really sure what you’re getting at. The problem isn’t string formatting, it’s that you simply can’t get the source ip (from the packet buffer) and the http uri (from the http uri buffer) in the same lua script.

I’m sorry, I’m just trying to help. I thought I saw that done in that http output suricata-verify test by means of the SCFlowTuple(), so I assumed it is possible. But I don’t have more knowledge to help you further, right now.

Edit: It actually does work, I had something wrong in the previous version of my script.

Would something like this work for you?

{ Packet n. 0
10/06/2015-15:16:43.137833
[**]
Packet info:
Source IP: 10.16.1.11 source port: 59733 Destination IP: 104.131.202.103 destination port 80 http     uri /base64-hello-world.txt}

I tinkered with the script below and that was the output. Something else is still needed for it to log more packets, but could be a start?

name = "test_packet_info.log"

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

function setup(args)
    filename = SCLogPath() .. "/" .. name
    file = assert(io.open(filename, "a"))
    SCLogInfo("Lua test for packet and http info filename " .. filename)
    packet = 0 
end

function log(args)
    timestring = SCPacketTimeString()
    ipver, srcip, dstip, proto, sp, dp = SCPacketTuple()

    http_uri = HttpGetRequestUriRaw()
    if http_uri == nil then
        http_uri = "<unknown>"
    end 
    http_uri = string.gsub(http_uri, "%c", ".")

    file:write ("{ Packet n. " .. packet .. "\n " .. timestring .. "\n[**]\nPacket info: \nSource IP: " .. srcip .. " source port: " .. sp .. " Destination IP: " .. dstip .. " destination port " .. dp .. " http uri " .. http_uri .. "}\n")
    packet = packet + 1 
end

function deinit(args)
    SCLogInfo ("Test finished");
    file:close(file)
end

Anyway, good luck!

Sorry if I came off as rude, that is not my intention.

Your code does have the right information, unfortunately I’m working with suricata lua detection and not logging. I want to use the lua script I’m writing to trigger a rule, and you can’t use needs[“protocol”] = “http”, you have to use their buffers.

thanks

I’m sorry, too, for not being able to help, and for not understanding your request properly. Good luck, and if you come up with a solution, do share! :slight_smile:

Hi, @Joseph_Wills. I believe I’m having a similar problem to yours. Did you manage to come by a solution?

Turns out, in my case SCFlowTuple should be used instead of SCPacketTuple .

In case anyone ends up at this post, this is how I managed to get the source ip:

function init (args)
    local needs = {}
    needs["tls"] = tostring(true)
    return needs
end

function match(args)
    ipver, srcip, dstip, proto, sp, dp = SCFlowTuple()
    SCLogWarning(srcip)
    return 0
end
1 Like