[Snort-devel] base64_data and base64_decode -- how to use properly?

Joshua.Kinard at ...3108... Joshua.Kinard at ...3108...
Wed May 25 21:00:01 EDT 2011


Has anyone taken a look at this to verify if this is indeed a bug or is
this improper use on my part? 

Thanks!,

--J

-----Original Message-----
Sent: Thursday, May 19, 2011 12:01 AM
To: snort-devel at lists.sourceforge.net
Subject: [Snort-devel] base64_data and base64_decode -- how to use
properly?


Hi snort-devel,

I find the explanations of base64_data and base64_decode to not be 100%
clear in the manual on their usage, and I think I may have found some
minor bugs with them.  Can one of the devs provide clarity?

Page 160 of the snort manual has this as an example:

alert tcp $EXTERNAL_NET any -> $HOME_NET any \
(msg:"Base64 Encoded Data"; base64_decode; base64_data; \
content:"foo bar"; within:20;)

Is this valid?  'within' is a relative modifier, and should only be
applicable with two or more contents.  Yet, I tested a rule like this on
an HTTP packet whose URI string has some base64 data in it, and noted
the following issues:

1. The rule is never even processed UNLESS I include 'within' -- even
   if I only have 1 content.

2. I can mix 'base64_data' and 'rawbytes' together.  Per the manual and
   the VRT blog about kpyke and the "green curtain", 'base64_data' is a
   distinct buffer.  I shouldn't be able to mix these two I believe.

So I turned on snort's debugging (export SNORT_DEBUG=16384), and hacked
a single Wireshark PCAP file together with a single packet of HTTP (a
GET request) with a base64 string in the middle of the URI:

GET /foo.php?x=Zm9vYmFyYmF6Zm9v&a=1&b=2&c=3
(The base64 is 'foobarbazfoo')

The Sample rule:
alert tcp any any <> any any (msg:"Base64 Test"; flow:stateless;
base64_decode; base64_data; content:"foobarbaz"; sid:42000054; rev:1;
gid:1; priority:2; classtype:string-detect;)

If I run the above rule against the single-packet capture file, then the
rule is never profiled.  It seems 'within' is mandatory with the base64
options, even if there is just a single content match.  This seems
broken to me.

So I added 'within:9;' to the rule along with 'rawbytes', and receive
the following:
sp_pattern_match.c:185: Plugin: PatternMatch Initialized!
sp_pattern_match.c:198: In PayloadSearchInit()
sp_pattern_match.c:335: OTN function PatternMatch Added to rule!
sp_pattern_match.c:616: Pattern within = 9
sp_pattern_match.c:1958: CheckPatternANDMatch: sp_pattern_match.c:2036:
Using Full Packet Data!
sp_pattern_match.c:1819: Using Doe Ptr
sp_pattern_match.c:1856: Changing Depth from -870647207 to 9
sp_pattern_match.c:1866: returning because base_ptr is out of bounds
start_ptr: 0x2ab8cd4ae046 end: 0x2ab8cd4ae119 base: 0x12fe6c0

This indicates using 'rawbytes' is bad and a check is needed to error
out.  So I removed 'rawbytes' and ran it again:
sp_pattern_match.c:185: Plugin: PatternMatch Initialized!
sp_pattern_match.c:198: In PayloadSearchInit()
sp_pattern_match.c:335: OTN function PatternMatch Added to rule!
sp_pattern_match.c:616: Pattern within = 9
sp_pattern_match.c:1958: CheckPatternANDMatch: sp_pattern_match.c:1977:
Using Base64 Decode Buffer!
sp_pattern_match.c:1819: Using Doe Ptr
sp_pattern_match.c:1856: Changing Depth from 8 to -1
sp_pattern_match.c:1874: returning because depth is negative (-1)

Why is depth changed from 8 to -1?  My 'within' is for 9 bytes, not 8 or
-1.  So I removed a character to make it 8 bytes (content:"foobarba";
within:8;), and ran it again:
sp_pattern_match.c:185: Plugin: PatternMatch Initialized!
sp_pattern_match.c:198: In PayloadSearchInit()
sp_pattern_match.c:335: OTN function PatternMatch Added to rule!
sp_pattern_match.c:616: Pattern within = 8
sp_pattern_match.c:1958: CheckPatternANDMatch: sp_pattern_match.c:1977:
Using Base64 Decode Buffer!
sp_pattern_match.c:1819: Using Doe Ptr
sp_pattern_match.c:1856: Changing Depth from 8 to 8
sp_pattern_match.c:1907: uniSearchReal:
 sp_pattern_match.c:1910:    p->data: 0x12fe6c0
   doe_ptr: 0x12fe6c0
   base_ptr: 0x12fe6c0
   depth: 8
   searching for: 666F6F6261726261
mstring.c:679: buf: 0x12fe6c0  blen: 8  ptrn: 0x12bb22c0  plen: 8
mstring.c:683: buf: 1844FF7E8A298696
mstring.c:686: ptrn: 666F6F6261726261
mstring.c:688: buf: 0x12fe6c0  blen: 8  ptrn: 0x12bb22c0  plen: 8
mstring.c:722: no match: compares = 0.

The buffer (1844FF7E8A298696) seems to be completely invalid.

So as far as I can tell, base64_data and base64_decode really only seem
to be useful for SMTP MIME decoding.  Their use with anything else seems
to be totally broken.  Or my use of the rule options are incorrect.

Questions:
1. Why does it seem the base64 buffer is only 8 bytes large?
2. Why does 'within' have to be specified for a rule to even work with
the base64 options?
3. Can base64_decode/base64_data decode base64 data embedded in the
middle of non-base64 data?
4. Can base64 decoding happen on rawbytes buffers?

Thoughts, explanations, ideas, clarifications?


Thanks!,

--J




More information about the Snort-devel mailing list