[Oisf-devel] RFC: lua scripting flowvar access

Victor Julien victor at inliniac.net
Fri Apr 19 10:01:39 UTC 2013


> On 18/04/13 17:01, Victor Julien wrote:
>> Funded by Emerging Threats, I've been working on giving the lua scripts
>> access to flowvars.
>>
>> Currently only "flowvars" are done, "flowints" will be next. Please
>> review the code at:
>> https://github.com/inliniac/suricata/tree/dev-lua-flowvar
>>
>> Pcre based flowvar capturing is done in a post-match fashion. If the
>> rule containing the "capture" matches, the var is stored in the flow.
>>
>> For lua scripting, this wasn't what the rule writers wanted. In this
>> case, the flowvars are stored in the flow regardless of a rule match.
>>
>> The way a script can start using flowvars is by first registering which
>> one it needs access to:
>>
>> function init (args)
>>     local needs = {}
>>     needs["http.request_headers.raw"] = tostring(true)
>>     needs["flowvar"] = {"cnt"}
>>     return needs
>> end
>>
>> More than one can be registered, e.g.:
>>
>>     needs["flowvar"] = {"cnt", "somevar", "anothervar" }
>>
>> The maximum is 15 per script. The order of the vars matters. As Suricata
>> uses id's internally, to use the vars you have to use id's as well. The
>> first registered var has id 0, 2nd 1 and so on:
>>
>> function match(args)
>>     a = ScFlowvarGet(0);
>>     if a then
>>         print ("We have an A: " .. (a))
>>         a = tostring(tonumber(a)+1)
>>         print ("A incremented to: " .. (a))
>>         ScFlowvarSet(0, a, #a)
>>     else
>>         print "Init A to 1"
>>         a = tostring(1)
>>         ScFlowvarSet(0, a, #a)
>>     end
>>
>>     print ("A is " .. (a))
>>     if tonumber(a) == 23 then
>>         print "Match!"
>>         return 1
>>     end
>>
>>     return 0
>> end
>>
>> You can also use a var:
>>
>> function init (args)
>>     local needs = {}
>>     needs["http.request_headers.raw"] = tostring(true)
>>     needs["flowvar"] = {"blah", "cnt"}
>>     return needs
>> end
>>
>> local var_cnt = 1
>>
>> function match(args)
>>     a = ScFlowvarGet(var_cnt);
>>     if a then
>>         print ("We have an A: " .. (a))
>>         a = tostring(tonumber(a)+1)
>>         print ("A incremented to: " .. (a))
>>         ScFlowvarSet(var_cnt, a, #a)
>>     else
>>         print "Init A to 1"
>>         a = tostring(1)
>>         ScFlowvarSet(var_cnt, a, #a)
>>     end
>>
>>     print ("A is " .. (a))
>>     if tonumber(a) == 23 then
>>         print "Match!"
>>         return 1
>>     end
>>
>>     return 0
>> end
>>
>> Flowvars are set at the end of the rule's inspection, so after the
>> script has run.
>>
>> When multiple stores are done from the script and/or pcre, the last
>> match will win. So if order matters, rule priority can be used to
>> control inspection order.
>>
>> Thoughts, comments, and code review highly welcomed.
>>

On 04/18/2013 08:02 PM, Chris Wakelin wrote:> Sounds very useful!
>
> My first thoughts are
>
> 1) We can return specific messages for particular hits in a suspicious
> .jar, (possibly costing some performance to have rules to check the
> flowvar and display the appropriate messages)

Right. I want to add pktvar support as well, where the variable would
only live in the packet ctx. That may be better suited for this case.

> 2) Blackhole/Cool/SofosFO encrypt their payloads with a base integer
> that is specified in the URI. We could set a flowvar using pcre on the
> URI, then check whether it decodes the payload in Lua (though actually,
> the ET Luajit XOR script deduces the base from the first two bytes being
> "MZ" in an executable).

Should be possible, yeah.

> I'm sure we'll come up with other uses :)

Great, glad it appears to be useful :)

-- 
---------------------------------------------
Victor Julien
http://www.inliniac.net/
PGP: http://www.inliniac.net/victorjulien.asc
---------------------------------------------




More information about the Oisf-devel mailing list