[Oisf-devel] New Features: Flowint

Matt Jonkman jonkman at jonkmans.com
Mon Jan 11 17:44:51 UTC 2010


We have a great number of new features coming out with Suricata. Many
are already there so we want to start talking about them and making
everyone aware. To be clear though, Suricata supports all of the current
rule syntax directives. We're just adding new to accommodate the new
features we're building.

The first one I'd like to bring to your attention is Flowint. This is a
precursor to the Global Variables task we have due very soon, which will
allow the capture, storage and comparison of data in a variable. Cool,
yes. But it's not just for the stream, it'll be as the name implies
Global. So you can compare data from packets in unrelated streams. More
on that when it's ready, probably around February 2010.

Flowint allows storage and mathematical operations using variables. It
operates much like flowbits but with the addition of mathematical
capabilities and the fact that an integer can be stored and manipulated,
not just a flag set. We can use this for a number of very useful things,
such as counting occurrences, adding or subtracting occurrences, or
doing thresholding within a stream in relation to multiple factors. This
will be expanded to a global context very soon so we can do these
operations between streams. More on that when it's in there!



The syntax is as follows:


flowint: <var>, <set|isset|unset>;
Define a var (not required), or check that one is set or not set.



flowint: <var>, <operator>, <var or integer>;
flowint: <var>, < +,-,=,>,<,>=,<=,==, != >, <var or integer>;
Compare or alter a var. Add, subtract, compare greater than or less
than, greater than or equal to, and less than or equal to are available.
The item to compare with can be an integer or another variable.


For example, lets say we want to count how many times a username is seen
in a particular stream and alert if it's over 5.

alert tcp any any -> any any (msg:"Counting Usernames"; content:"jonkman"; \
flowint: usernamecount, +, 1; flowint:noalert;)
This will count each occurrence and increment the var usernamecount and
not generate an alert for each.

Now say we want to generate an alert if there are more than five hits in
the stream.

alert tcp any any -> any any (msg:"More than Five Usernames!";
content:"jonkman"; \
flowint: usernamecount, +, 1; flowint:usernamecount, >, 5;)
So we'll get an alert ONLY if usernamecount is over five.

So now lets say we want to get an alert as above but NOT if there have
been more occurrences of that username logging out. Assuming this
particular protocol indicates a log out with "jonkman logout", lets try:

alert tcp any any -> any any (msg:"Username Logged out"; content:"logout
jonkman"; \
flowint: usernamecount, -, 1; flowint:usernamecount, >, 5;)
So now we'll get an alert ONLY if there are more than five active logins
for this particular username.

This is a rather simplistic example, but I believe it shows the power of
what such a simple function can do for rule writing. I see a lot of
applications in things like login tracking, IRC state machines, malware
tracking, and brute force login detection.


Lets say we're tracking a protocol that normally allows five login fails
per connection, but we have a vulnerability where an attacker can
continue to login after that five attempts, and we need to know about it.

alert tcp any any -> any any (msg:"Start a login count"; content:"login
failed"; \
flowint:loginfail, notset; flowint:loginfail, =, 1; flowint:noalert;)
So we detect the initial fail if the variable is not yet set and set it
to 1 if so. Our first hit.

alert tcp any any -> any any (msg:"Counting Logins"; content:"login
failed"; \
flowint:loginfail, isset; flowint:loginfail, +, 1; flowint:noalert;)
We are now incrementing the counter if it's set.

alert tcp any any -> any any (msg:"More than Five login fails in a
Stream"; content:"login failed"; \
flowint:loginfail, isset; flowint:loginfail, >, 5;)
Now we'll generate an alert if we cross five login fails in the same
stream.


But let's also say we also need alert if there are two successful logins
and a failed login after that.

alert tcp any any -> any any (msg:"Counting Good Logins"; content:"login
successful"; \
flowint:loginsuccess, +, 1; flowint:noalert;)

Here we're counting good logins, so now we'll count good logins relevant
to fails:

alert tcp any any -> any any (msg:"Login fail after two successes";
content:"login failed"; \
flowint:loginsuccess, isset; flowint:loginsuccess, =, 2;)



Here are some other general examples:

alert tcp any any -> any any (msg:"Setting a flowint counter";
content:"GET"; \
flowint:myvar, notset; flowint:maxvar,notset; flowint:myvar,=,1;
flowint: maxvar,=,6;)

alert tcp any any -> any any (msg:"Adding to flowint counter";
content:"Unauthorized"; \
flowint:myvar,isset; flowint: myvar,+,2;)

alert tcp any any -> any any (msg:"if the flowint counter is 3 create a
new counter"; content:"Unauthorized"; \
flowint:myvar, isset; flowint:myvar,==,3; flowint:cntpackets,notset;
flowint:cntpackets, =, 0;)

alert tcp any any -> any any (msg:"and count the rest of the packets
received without generating alerts!!!"; \
flowint:cntpackets,isset; flowint:cntpackets, +, 1; flowint:noalert;)

alert tcp any any -> any any (msg:" and fire this when it reach 6";
flowint: cntpackets, isset; \
flowint: maxvar,isset; flowint: cntpackets, ==, maxvar;)



----------------------------------------------------
Matthew Jonkman
Emerging Threats
Open Information Security Foundation (OISF)
Phone 765-429-0398
Fax 312-264-0205
http://www.emergingthreats.net
http://www.openinfosecfoundation.org
----------------------------------------------------

PGP: http://www.jonkmans.com/mattjonkman.asc



More information about the Oisf-devel mailing list