working with MS15-034

All,

I'm working on a bro script to detect attempts for the
recently-announced IIS attack. I've hit an interesting issue: There's a
magic number that gets sent in the HTTP "RANGE" header to trigger the
vulnerability, and that number is 2^64. This is right at the edge of
what a "count" variable can hold, and it wraps around a regular "int"
variable.

I'd like to be able to detect anyone sending any number >= 2^64 in a
RANGE header, but I don't see how to do that with count variables in
bro. Does anyone have any ideas of how I can do this? Right now I'm
looking at doing something truly nasty, like comparing the length of the
strings holding the Range values. I'm *really* not happy with that,
though...it feels like a really ugly hack.

aaron

Forwarding to the rest of the Bro list ...

True, but I was hoping to do more than just detect the magic number. I
was hoping to be able to say something along the lines of:

  if (name == "RANGE" && value > 2^64 )

My thinking here is that I don't want to play whack-a-mole with magic
numbers. I would like to flag any request for an offset that big as a
potential problem.

aaron

You can use to_double:

$ bro -e ‘print to_double(“987654321123456789”);’
9.876543e+17

–Vlad

I agree, I think double's are the way to go ... but the behavior is
odd: http://try.bro.org/#/trybro/saved/3780

It doesn't recognize the numbers as being equal.

Josh

Better version here: http://try.bro.org/#/trybro/saved/3782

Well… they’re not equal. :slight_smile:

magic is 18446744073709551615,
while d is 18446740000000000000

See this:

http://try.bro.org/#/trybro/saved/3786

Thanks for the info. One question: if I declare:

const max_val = 1.8446744073709551615e+19;

Will the double keep all that precision?

aaron

This is what I’ve been playing with: http://try.bro.org/#/trybro/saved/3789.

Not sure how it will run in production.

Tim

Probably when it does the comparison, bro is internally using the full value not the scientific notation. If you turn 1.844674e+19 into a number you get 18446740000000000000 which is indeed less than 18446744073709551615. The fmt just truncates it down and prints the scientific notation while the mathematical comparison uses the full value.

Seems like it would be fine in production. There are multiple ways to
detect this vulnerability (including one not yet mentioned here that
was posted in the Bro IRC channel the other day). Personally I use a
script that looks for inbound connections that have a RANGE header,
save the RANGE value, then checks to see if the internal server
responded with the status code 416 (at which point the notice is fired
with the RANGE value included in it) ... this is vulnerability does a
good job of showing how flexible Bro can be with detection.

Stupid question: Since the goal is an overflow of a 64 bit number, why not

to_double("Range_targe") > 9.1e+17?

You could theoretically have someone who really really wants byte 18446740000000000000 in a file, but really, how does the semantics work for "normal"?

Many thanks for the help, everyone.

In case others are interested, here's where I ended up for the MS15-034
detector script. The reason for all the string splits is that I noticed
some legit "range" requests on my network included multiple ranges,
separated by commas. So, I had to check all of them.

https://gist.github.com/g-clef/063592400b111c76f760#file-ms15-034-bro

Comments/speed improvements always welcome.

aaron