Archive for the ‘3-err’ category

Weekend Challenge – Hint

December 1st, 2009

Wow, the sound of crickets is deafening. Surely someone has the skills to get us through this dilemma?  ;)

OK, some hints to get you through the challenge. Let’s start by solving this as an IPv4 address and then we’ll work our way into IPv6. Assume the address range we want to capture is 192.168.1.10 – 192.168.1.20. The big problem is the IPs are not on an even byte boundary. We could do something like:

src net 192.168.1.0/27

but that would give us addresses .0 – .31, more IPs than we actually wanted to see. To solve this problem we’ll need to use some operators and primitives.  One possibility is:

(ip[12]=192 and ip[13]=168 and ip[14]=1 and (ip[15]>=10 and ip[15]<=20))

Starting with the inner most brackets, the above statement reads “byte 15 must be greater than or equal to 10, but it also must be less than or equal to 20. If this statement is true, make sure byte 12 is equal to 192, byte 13 is equal to 168 and byte 14 is equal to 1.”

Can we shorten this expression? Absolutely! First we must convert it to Hex however. Why Hex? If I write a statement such as “ip[12:2]=” tcpdump will assume that the result will be a 16-bit number, not two 8-bit numbers. This is why you can write something like “tcp[2:2]=12345″ and have it work. tcpdump converts the two bytes into a 16-bit value and matches it against the value you specified. By converting to Hex we avoid this problem. So:

192.168.1.10 = 0xC0A8010A

192.168.1.20 = 0xC0A80120

Now we simply write our expression:

ip[12:4]>=0xC0A8010A and ip[12:4]<=0xC0A80120

That’s all there is to it.

While IPv4 uses 4 byte addresses, IPv6 uses 16 bytes. Because the addresses are so long, we write them in Hex to save some space. So the addresses I gave you in the challenge were:

2001:0db8:0000:0000:0000:0000:0000:0010

2001:0db8:0000:0000:0000:0000:0000:0020

Notice I didn’t initially write them that way. There’s a few conventions you can use to save space when writing an IPv6 address. First, we can truncate leading zeroes. So:

2001:0db8:0000:0000:0000:0000:0000:0010

becomes:

2001:db8:0000:0000:0000:0000:0000:10

Now, see all those zeroes in the middle? We can chop them out too. When you see “::” that means to fill in that space with enough zeroes to expand the address back out to 16 bytes. So add in this trick as well and we get:

2001:db8::10

Far easier to write. The caveat is you can only remove one group of zeroes with the double colon trick. Consider the following address:

2001::1234::10

We have no idea where to place the byte sequence “1234″ in the address. It start anywhere from byte 6 through byte 12.

When working with IPv4, tcpdump and Windump use the protocol keyword “ip”, as shown in the above examples. The IPv6 compliment to that is “ip6″. Where’s the source address field in the IPv6 header? Well I can’t give you all there answers or it is no longer a “challenge” :)

Weekend Challenge

November 27th, 2009

Here’s another challenge to test your bit wienie skills:

Write a tcpdump or Windump filter that will capture all traffic with a source IPv6 address of 2001:db8::10 through 2001:db8::20. Pretty easy, right? If you have not tried it, your going to find that tcpdump/Windump throws a few curves at you.

To check your work, here’s a capture file:

ipv6-icmp

The file contains a mix of source IPv6 addresses. Obviously your filter should only display the specified range of addresses.

The winner gets to inspire awe and admiration in lesser geeks.  ;)

Oh where, oh where can WScale be?

November 20th, 2009

If this challenge seemed harder than it should be,you are on the right track. ;)

I ran across this problem when writing my Packet Decode tool. I have to say, it was a cool exercise for me, as I never really thought about creating tcpdump and Wireshark filters for every possible IP, TCP, UDP and ICMP field and/or value. By far the TCP options field is the most “broken” from a packet decode perspective than any other IP field.

First let’s talk about how the TCP options should have been implemented. If you look at the IPv4 options field, it begins with a “Type” identifier. If you are interested in a specific IP option, it is just a matter of checking this field for the right bit combination. Had the TCP options been implemented this way, this challenge would have been pretty straight forward.

Just about all TCP options have a “Kind” and a “Length” field, both of which are 1 byte in size. The exceptions are “End of Option List” and “No-Operation” which only have a Kind field, and thus are one byte in size. Here’s a list of the common TCP options:

tcp-options

Page 15 of RFC 793 tells us “The TCP header (even one including options) is an integral number of 32 bits long.” In other words, the TCP header size in bytes must be evenly divisible by four (20 bytes, 24 bytes, etc.). If you look at the list of TCP options, only “maximum segment size” is divisible by four. So the use of any other options are going to require padding.

How the padding should be applied is a bit unclear. If we look at page 26 of RFC 1323 we find this:

APPENDIX A:  IMPLEMENTATION SUGGESTIONS

   The following layouts are recommended for sending options on non-SYN
   segments, to achieve maximum feasible alignment of 32-bit and 64-bit
   machines.

       +--------+--------+--------+--------+
       |   NOP  |  NOP   |  TSopt |   10   |
       +--------+--------+--------+--------+
       |          TSval   timestamp        |
       +--------+--------+--------+--------+
       |          TSecr   timestamp        |
       +--------+--------+--------+--------+

Note the NOP padding appears before the timestamp option, not at the end like you might expect. Also note the RFC specifically says this is for “non-SYN segments” and that it is “recommended”, not required. Seems however that most operating systems follow this recommendation and always place padding before the Kind and Length bytes. I’ve checked Windows, Linux, Mac, various hardware, etc. and they all put the padding at the beginning.

So we can count on this being the “standard”, right? Not quite.  Page 17 of RFC 793 describes NOP this way:

        This option code may be used between options, for example, to
        align the beginning of a subsequent option on a word boundary.
        There is no guarantee that senders will use this option, so
        receivers must be prepared to process options even if they do
        not begin on a word boundary.

In other words, its not just that NOP may or may not show up at the beginning, NOP might not be used at all! It is entirely legal to layout the TCP option field with no NOP padding and just use End of Option List as filler at the end to achieve the proper boundary.

So what do we end up with for a filter? If we count on NOP before the option we end up with a filter that looks like this:

tcp[13]&2=2 and tcp[12]&240>80 and ((tcp[20]=1 and tcp[21:2]=0×0303) or (tcp[24]=1 and tcp[25:2]=0×0303) or (tcp[28]=1 and tcp[29:2]=0×0303) or (tcp[32]=1 and tcp[33:2]=0×0303) or (tcp[36]=1 and tcp[37:2]=0×0303) or (tcp[40]=1 and tcp[41:2]=0×0303) or (tcp[44]=1 and tcp[45:2]=0×0303) or (tcp[48]=1 and tcp[49:2]=0×0303) or (tcp[52]=1 and tcp[53:2]=0×0303) or (tcp[56]=1 and tcp[57:2]=0×0303))

To break down what this filter is doing:

  • Only check SYN & SYN/ACK packets:  tcp[13]&2=2
  • TCP header is greater than 20 bytes (options are set): tcp[12]&240>80
  • Check the first byte of each four byte boundary for NOP: tcp[20]=1, tcp[24=1, ...
  • Check the next two bytes to see if Kind=3 and Length=3: tcp[21:2]=0×0303, tcp[25:2]=0×0303, …

If however we want to ensure that we catch all possibilities in case a system does not implement NOP we end up with:

tcp[13]&2=2 and tcp[12]&240>80 and (tcp[20:2]=0×0303 or tcp[21:2]=0×0303 or tcp[22:2]=0×0303 or tcp[23:2]=0×0303 or tcp[24:2]=0×0303 or tcp[25:2]=0×0303 or tcp[26:2]=0×0303 or tcp[27:2]=0×0303 or tcp[28:2]=0×0303 or tcp[29:2]=0×0303 or tcp[30:2]=0×0303 or tcp[31:2]=0×0303 or tcp[32:2]=0×0303 or tcp[33:2]=0×0303 or tcp[34:2]=0×0303 or tcp[35:2]=0×0303 or tcp[36:2]=0×0303 or tcp[37:2]=0×0303 or tcp[38:2]=0×0303 or tcp[39:2]=0×0303 or tcp[40:2]=0×0303 or tcp[41:2]=0×0303 or tcp[42:2]=0×0303 or tcp[43:2]=0×0303 or tcp[44:2]=0×0303 or tcp[45:2]=0×0303 or tcp[46:2]=0×0303 or tcp[47:2]=0×0303 or tcp[48:2]=0×0303 or tcp[49:2]=0×0303 or tcp[50:2]=0×0303 or tcp[51:2]=0×0303 or tcp[52:2]=0×0303 or tcp[53:2]=0×0303 or tcp[54:2]=0×0303 or tcp[55:2]=0×0303 or tcp[56:2]=0×0303 or tcp[57:2]=0×0303 or tcp[58:2]=0×0303)

The difference with this filter is that we are checking Kind=3 and Length=3 all the way through the options field (as Elizabeth suggested).

Can either of these filters generate false positives? Absolutely! Two possibilities:

  1. The value of Timestamp may match the pattern we are looking for.
  2. The filter assumes a 40 byte option field. It could be less with these values in the payload.

So which filter should you use? The first will generate fewer false positives but miss systems that are RFC compliant but different from the norm. The second will always catch Window Scale if it has been set, but the chance of a false positive is higher.

I’m going to designate Elizabeth as the winner of the challenge. A few others were just as close but she was the only one with the guts to post her train of thought in the comments. I’m going to award a second prize to Jeff who came up with this solution partially kidding around:

tcpdump -nn | grep ‘wscale ‘ > wscale-matches.txt

This will not generate an actual packet capture, but you could do a:

tcpdump -nn -X -s 0 | grep ‘wscale ‘ > wscale-matches.txt

And then run the output through txt2cap to get it back into pcap format. He didn’t follow the challenge specifically, but you’ve gotta give kudos for thinking outside the box as this fixes all false positive issues. ;)

Elizabeth and Jeff, I’ll be contacting you both via e-mail. Congrats!

TCP Options – Final clue

November 19th, 2009

I’ve had one thread post and four e-mails that are soooooo close to the right answer. Here’s one last clue to hopefully get folks over the final hurdle.

I mentioned the helpful tshark command. Here’s the output:

C:\testing>tshark -n -r linux-syn.cap -T fields -e tcp.options
02:04:05:b4:04:02:08:0a:02:47:4a:a8:00:00:00:00:01:03:03:05

So what you have above is the TCP options section (byte 20 and higher) of the test packet. The Window Scale option is the last option in the list.

I know writing this filter is not easy. In fact that’s why I turned it into a challenge. It is possible however. ;)

PDF of “Protecting Against Targeted Attacks” talk

October 14th, 2009

Over the next few weeks I’ll be giving this talk in a number of locations. For those who attended and requested a PDF version of the slides, here is the link I promised:  protecting-against-targeted-attacks-R2

Tshark Challenge – Hints 3

October 7th, 2009

This is the third set of hints to the tshark decode challenge I issued last week. You can grab a copy of the decode file from the challenge page.

In my last post we spotted some discrepancies is the TCP stream. Let’s take a closer look at the payload to see if anything looks out of place. The command I’ll be using is:

tshark -r challenge1.cap -x | less

If you are running on Windows, replace the “less” command with the “more” command.

The “-x” switch will cause tshark to print the payload of each packet along with the header summary.  If you page down to packet 4 you should see:

4   0.030787 148.78.247.10 -> 12.33.247.4  HTTP GET /cfide/Administrator/startstop.html HTTP/1.0

0000  00 b0 d0 20 7d e3 00 50 8b ea 20 ab 08 00 45 00   … }..P.. …E.

0010  01 11 2a 96 00 00 31 06 cf d2 94 4e f7 0a 0c 21   ..*…1….N…!

0020  f7 04 69 2a 00 50 6a 97 b8 6f 3a 88 39 cd 80 18   ..i*.Pj..o:.9…

0030  ff ff 42 fc 00 00 01 01 08 0a 00 ec 48 4b 3d 76   ..B………HK=v

0040  0e 8b 47 45 54 20 2f 63 66 69 64 65 2f 41 64 6d   ..GET /cfide/Adm

0050  69 6e 69 73 74 72 61 74 6f 72 2f 73 74 61 72 74   inistrator/start

0060  73 74 6f 70 2e 68 74 6d 6c 20 48 54 54 50 2f 31   stop.html HTTP/1

0070  2e 30 0d 0a 48 6f 73 74 3a 20 31 32 2e 33 33 2e   .0..Host: 12.33.

0080  32 34 37 2e 34 0d 0a 55 73 65 72 2d 41 67 65 6e   247.4..User-Agen

0090  74 3a 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 5b   t: Mozilla/5.0 [

00a0  65 6e 5d 20 28 57 69 6e 39 35 3b 20 55 29 0d 0a   en] (Win95; U)..

00b0  52 65 66 65 72 65 72 3a 20 68 74 74 70 3a 2f 2f   Referer: http://

00c0  31 32 2e 33 33 2e 32 34 37 2e 34 2f 0d 0a 58 2d   12.33.247.4/..X-

00d0  46 6f 72 77 61 72 64 65 64 2d 46 6f 72 3a 20 31   Forwarded-For: 1

00e0  34 38 2e 36 34 2e 31 34 37 2e 31 36 38 0d 0a 43   48.64.147.168..C

00f0  61 63 68 65 2d 43 6f 6e 74 72 6f 6c 3a 20 6d 61   ache-Control: ma

0100  78 2d 73 74 61 6c 65 3d 30 0d 0a 50 72 61 67 6d   x-stale=0..Pragm

0110  61 3a 20 6e 6f 2d 63 61 63 68 65 0d 0a 0d 0a ce   a: no-cache…..

0120  f8 43 76                                                    .Cv

This is the “GET” request for the suspicious file name. There are a couple of fields in this payload that do not look right. The “HOST:” field should identify which Web server the client was attempting to access. This should always be a fully qualified domain name, like “www.fubar.com” or similar. The fact that the server’s IP address is listed tells me a Web browser was not used to generate this session.

It is possible to host multiple Web sites on the same physical server. The server figures out which specific site you want to access by analyzing this host field. If Web browsers didn’t follow this rule, co-location servers with multiple sites hosted on the same physical box would never work. So this tells me the client is going after the actual Web server process, not a Web site hosted on the system.

The “User-Agent:” field looks odd as well. While it is possible the client is still running Windows 95, it is unlikely.

The referer field is incorrect as well. This should show us the full URI the client was accessing when they were directed to this page. It should include the fully qualified domain name, as well as the exact page on the site that referred them to this page. In fact if the referer is a search engine, the field will also include what search parameters were used when they were directed to our site. Listing an IP address is completely incorrect.

There is one last interesting piece of information in this payload. The “X-Forwarded-For:” field tells us that the source IP address in the IP header is acting as an HTTP proxy for whatever IP address is listed in this field. It is not uncommon for attackers to bounce their attacks off of a public proxy server. This way if you detect the attack in your Web server access log, you will think the source IP address is the hostile entity as the X-Forwarded-For field will not be listed.

So we have a suspect file request, from an IP that is trying to hide their identity, using packets that have suspicious values. We don’t need a IDS to tell us this is probably an attacker looking for a known to be vulnerable file.

Now take a look at packets 8 through 17. Each one is the server attempting to tell the client “I’m sorry, I’m not running that vulnerable file. Please try a different vulnerable file if you want to compromise me”, via 404 error messages.

So the flow goes something like this:

  • Client sends a probe for a potentially vulnerable file
  • Server resets the connection
  • Client resets the connection
  • Server continually tells the client it does not have that file

So why the resets and why did the server ignore them? Tune in tomorrow to find out…

Tshark Challenge – Hints2

October 6th, 2009

Yesterday we left off taking an initial look at the decode file. A first pass left us scratching our head because we saw a 404 error followed by multiple retransmissions. In this hint we’ll dig into the trace a little deeper.

Let’s go back to our initial decode and follow what happened packet by packet:

tshark -r challenge1.cap

1   0.000000 148.78.247.10 -> 12.33.247.4  TCP 26922 > http [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=0 TSV=15485003 TSER=0

2   0.000080  12.33.247.4 -> 148.78.247.10 TCP http > 26922 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=1031147147 TSER=15485003 WS=0

3   0.029341 148.78.247.10 -> 12.33.247.4  TCP 26922 > http [ACK] Seq=1 Ack=1 Win=65535 Len=0 TSV=15485003 TSER=1031147147

4   0.030787 148.78.247.10 -> 12.33.247.4  HTTP GET /cfide/Administrator/startstop.html HTTP/1.0

5   0.030841  12.33.247.4 -> 148.78.247.10 TCP http > 26922 [ACK] Seq=1 Ack=222 Win=6432 Len=0 TSV=1031147150 TSER=15485003

6   0.031319  12.33.247.4 -> 148.78.247.10 TCP http > 26922 [RST, ACK] Seq=1 Ack=222 Win=0 Len=0

7   0.031385 148.78.247.10 -> 12.33.247.4  TCP [TCP ACKed lost segment] 26922 > http [RST, ACK] Seq=1 Ack=222 Win=0 Len=0

8   0.031610  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

9   0.031664  12.33.247.4 -> 148.78.247.10 HTTP HTTP/1.1 404 Not Found  (text/html)

10   0.251838  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

11   0.711825  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

12   1.631812  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

13   3.471773  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

14   7.153143  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

15  14.511594  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

16  29.231324  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

17  58.670815  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

Our first three packets are the TCP handshake. This portion looks pretty normal. In packet 4, we see the client send a “GET” request for a file. This file request strikes me as suspicious. A file named “startstop.html” in the “Administrator” directory does not exactly sound like a file we would want to be serving up to the public at large. We’ll make a note of this and come back to it later.

In packet 5 we see the server acknowledge the data request. After this packet, things get a little odd. In packet 6, we see the server transmit a reset packet to kill the connection. This is an indication that the server feels something has gone wrong with the session and that it is unrecoverable. This is extremely odd behavior for TCP as it tries very hard to be reliable. It normally will transmit multiple attempts to reestablish a connection if it thinks something went wrong. You can see normal recovery behavior in packets 10 through 17, which more closely matches how TCP will attempt to maintain connectivity. There is a .5 ms difference in the timestamp between packets 5 and 6. A normal operating system would never determine in that short a period of time that the TCP session is unrecoverable.

In packet 7, things continue to act strangely. We see the client respond to the server’s reset packet with a reset packet of its own. This is certainly not normal IP behavior as the RFCs state you should never respond to an error packet. So during a normal session you would never see this type of error exchange. Something is obviously very wrong.

In packet 9, we see the server send a 404 error message. There are a couple of problems here. To start, the server already sent a reset indicating it considered the session to be unrecoverable. A system should never continue to send data after issuing a reset packet. In fact, the server continues to transmit all the way to packet 17. What makes this activity even stranger is that the client has issued a reset as well. So the server is not only ignoring the fact that it issued a reset, it is also ignoring the reset sent by the client.

So needless to say this is very strange TCP behavior. In my next post I’ll dig deeper into the payloads to get a better look at what is going on.

Tshark Challenge – Hints1

October 5th, 2009

Last week I posted a Libpcap file and challenged you to figure out as much as you could about the trace using tshark. In this post I’ll start you through the process of analyzing the decode. I WIL NOT cover it completely. My goal here is to give a leg up to the folks who do not even know where to start. I’ll add more details as the week goes on.

Getting started

The first thing you should do is have a look at the contents of the file. I’ll use the –r switch to read in the contents of the file. This will override tshark’s default setting of sniffing on the first detected interface. Normally I would pipe the output through the “less” command (or “more” on Windows), but there are only 17 packets in the file.

tshark -r challenge1.cap

1   0.000000 148.78.247.10 -> 12.33.247.4  TCP 26922 > http [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=0 TSV=15485003 TSER=0

2   0.000080  12.33.247.4 -> 148.78.247.10 TCP http > 26922 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=1031147147 TSER=15485003 WS=0

3   0.029341 148.78.247.10 -> 12.33.247.4  TCP 26922 > http [ACK] Seq=1 Ack=1 Win=65535 Len=0 TSV=15485003 TSER=1031147147

4   0.030787 148.78.247.10 -> 12.33.247.4  HTTP GET /cfide/Administrator/startstop.html HTTP/1.0

5   0.030841  12.33.247.4 -> 148.78.247.10 TCP http > 26922 [ACK] Seq=1 Ack=222 Win=6432 Len=0 TSV=1031147150 TSER=15485003

6   0.031319  12.33.247.4 -> 148.78.247.10 TCP http > 26922 [RST, ACK] Seq=1 Ack=222 Win=0 Len=0

7   0.031385 148.78.247.10 -> 12.33.247.4  TCP [TCP ACKed lost segment] 26922 > http [RST, ACK] Seq=1 Ack=222 Win=0 Len=0

8   0.031610  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

9   0.031664  12.33.247.4 -> 148.78.247.10 HTTP HTTP/1.1 404 Not Found  (text/html)

10   0.251838  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

11   0.711825  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

12   1.631812  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

13   3.471773  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

14   7.153143  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

15  14.511594  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

16  29.231324  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

17  58.670815  12.33.247.4 -> 148.78.247.10 TCP [TCP Retransmission] [TCP segment of a reassembled PDU]

Some details that immediately grab my attention:

  1. This is an HTTP session
  2. The connection attempted to access a file that does not exist (404 error in #9)
  3. There were communication issues with the session (#10-17 are retransmissions)

So right away this trace leaves me asking a few questions:

  1. What’s up with the request for a file that does not exist?
  2. Why are we having communication problems?

That’s it for now. Tomorrow I’ll post another hint.

Tshark Decode Challenge

October 2nd, 2009

In my last post I covered tshark and discussed how to manipulate the output during a decode. There is no better way to learn than by doing, so I decided to post a challenge. In this post I’ll provide a Libpcap file. Your mission Mr. Phelps, should you choose to accept it, is to attempt to identify what is going on within the decode file using tshark.

Installing tshark

In order to install tshark, you need to install Wireshark. You can grab a current copy from the download page. Once you do, the installation process is dependent on what platform you are using:

Linux/UNIX

If you are running Fedora or Red Hat, you do not need to visit the download page. You can install Wireshark directly through Yum:

su –

yum –y install wireshark.i586

If you are running a UNIX flavor or some other Linux distro, you may need to grab the tar archive from the above link and compile Wireshark for your system. Pay close attention to the dependencies as there are a lot of them. Ensure that “./configure” completes successfully before building your binaries.

Windows

  1. Download the self-extracting executable
  2. Run the executable
  3. Accept Unknown Publisher screen by clicking “run” button
  4. Follow the on-screen prompts accepting the defaults
  5. Install WinPcap (make sure box is checked)
  6. Install NPF service if non-Administrator users will be running the tool
  7. Add “C:\Program Files\Wireshark” to the end of your path statement

OS X

  1. Select the image that matches your processor type (Intel or PPC)
  2. Open with DiskimageMounter
  3. Open the “Read me first.rtf”
  4. Follow the “Quick Setup” instructions

The challenge

Here’s the challenge file:

challenge1.cap

And here are the hashes of the file to verify your download:

MD5: ea92f08d9ba104c6cf7756564eb5aef9  challenge1.cap
SHA-1: 71041ab0f670c5b9558183a56fe1bb80e8b10506  challenge1.cap

Good luck and starting next week I’ll post a little more info about the file every day to help move you through the decode process.

How To Review A Firewall Log In 15 Min Or Less – Part 2

September 29th, 2009

In my last post I introduced the concept of using white listing in order to review firewall logs. I discussed how this process can both simplify as well as expedite the log review process, by automating much of the up front work. In this post we will look at some actual examples, as well as start creating a firewall log parsing script.

The basics of grep

In order to show you the process of white listing your firewall logs, I am going to use grep. Grep is a standard Linux/UNIX tool, with free versions available for Windows (grab both the Binaries as well as the Dependencies). Grep is certainly not the most efficient tool for the job, but it is by far the simplest to learn. If you are a Perl, PHP, AWK&SED, SQL, etc. guru, by all means stick with your tool of choice. Simply mimic the process I’ve defined here using your appropriate command set.

Grep is a pattern-matching tool. It allows you to search one or more files looking for a specific pattern. When the pattern is found, the entire line is printed out. So for example the command:

grep 192.168.1.10 firewall.log

would produce all lines in the file “firewall.log” that contains the IP address “192.168.1.10”. Grep has a number of supported switches, but the only one we need for firewall log review is the “-v” switch. This switch tells grep to match all lines that DO NOT contain the specified pattern. So for example:

grep –v 192.168.1.10 firewall.log

would only print out lines that do not contain the specified IP address.

With grep, a period is actually a wild card character. So while I said the first grep command would match on the IP address 192.168.1.10, it could actually match on more than that. Grep interprets the string to read:

Match on: 192 <any single character> 168 <any single character> 1  <any single character> 10

If we want grep to match periods as periods, we have to preced them with a backslash character. So the proper syntax would actually be:

grep 192\.168\.1\.10 firewall.log

Finally, sometimes we want to match on multiple patterns that are strung together. For example what if we are only interested in 192.168.1.10 traffic when that’s the destination IP address? Depending on your firewall log format, the command may look something like this on a Linux or UNIX system:

grep ‘dst 192\.168\.1\.10’ firewall.log

On Windows, the command would look like this:

grep “dst 192\.168\.1\.10” firewall.log

Note the only difference is that Linux and UNIX uses single quotes, while Windows uses double quotes.

Logical AND’s and OR’s

Sometimes we need to match on multiple patterns within the same line. For example what if we only wish to see TCP/80 traffic to our Web server? In this case there are actually two patterns we wish to match on the same line. The problem is there may be other stuff in the middle we don’t care about.

To perform a logical AND, simply use the grep command twice on the same line. For example:

grep “dst 192\.168\.1\.10” firewall.log | grep “dst_port 80 ”

The pipe symbol simply lets you run the second grep command before execution ends. So the first grep command will grab all traffic going to 192.168.1.10 and then pass it to the second grep command. The second grep command then searches this output for all traffic headed to port 80. Look closely after the port number and you will see I included a space character. Without a space character, we could potentially match on port 800, 8080, etc.

Sometimes we may wish to match on either of two values. For example what if we wanted to see both HTTP and HTTPS traffic to our Web server? In this case we would need to do a logical AND combined with a logical OR. Here’s how to do that with grep:

grep ‘dst 192\.168\.1\.10’ firewall.log | grep ‘dst_port \(80 \|443 \)’

The first half of the command should look familiar, but the second half needs some explaining. We need to tell grep that the parenthesis characters are actual commands and not part of the string we wish to match. We do this by preceding them with a backslash character. The pipe character is what tells grep to process this command as a logical OR. Note the pipe also needs to be preceded by a backslash.

Sorting logs with grep

OK, so we have the basics, now let’s start applying them to reviewing a firewall log file. The first thing you need to do is get the log file into ASCII format. This is the native format for many firewalls, so no conversion may be required. If the log uses a proprietary format, the vendor usually supplies a tool to do the conversion. Personally I just send the logs to a SIM (http://www.chrisbrenton.org/2009/08/setting-up-a-security-information-management-system-sim-%E2%80%93-part-1/). From there you can simply copy them off to a working directory.

Next we need to open a text editor. While we can run our grep commands on the command line to test their accuracy, we want to place the commands in a shell script or batch file so they can be easily run later. For the rest of this post I will use single quotes, which is the syntax for both Linux and UNIX. Remember that your Windows version of grep may want to see double quotes instead.

The next step is to review the log file looking for traffic patterns you recognize. Let’s take an easy one like HTTP traffic to your Web server. Look closely at a log entry and identify what unique characteristics it has which tells you its HTTP traffic to your Web server. Most likely this will be the target IP address of your Web server, as well as a target port of TCP/80. Now simply create a grep command to copy these entries to a new file:

grep ‘dst 192\.168\.1\.10’ firewall.log | grep ‘dst_port 80 ’ > web_server_http.txt

Note that rather than print the output to the screen, we redirected it to a file with a descriptive name. That way the log entries are available for later review.

If our Web server is only offering HTTP, we should only see traffic headed to port TCP/80. Any other port connect attempts can be considered suspect traffic, and may be part of a scan or probe. With port TCP/80 traffic in it’s own file, we now simply redirect everything else to another file:

grep ‘dst 192\.168\.1\.10’ firewall.log | grep –v ‘dst_port 80 ’ > web_server_scan.txt

This should account for all traffic headed to our Web server. Now we need to get all of this saved traffic out of the way so it will be easier to spot other entries. While we could try to delete them, it would be prudent to keep an unmodified version of the firewall log just in case we need to refer back to it. The easiest way to handle this conflict is to simply create a new temporary file.

grep –v ‘dst 192\.168\.1\.10’ firewall.log > temp1.txt

Now we simply open “temp1.txt” and look for the next pattern we recognize. Let’s say that’s inbound and outbound SMTP. That section of our script may look something like this:

grep ‘dst 192\.168\.1\.12’ temp1.txt | grep ‘dst_port 25 ’ > smtp_inbound.txt

grep ‘dst 192\.168\.1\.12’ temp1.txt | grep –v ‘dst_port 25 ’ > smtp_server_scan.txt

grep –v ‘dst 192\.168\.1\.12’ temp1.txt > temp2.txt

grep ‘src 192\.168\.1\.12’ temp2.txt | grep ‘dst_port 25 ’ > smtp_outbound.txt

grep ‘src 192\.168\.1\.12’ temp2.txt | grep –v ‘dst_port 25 ’ > smtp_server_compromise.txt

grep –v ‘src 192\.168\.1\.12’ temp2.txt > temp3.txt

SMTP is a bidirectional service, so the first three lines take care of inbound traffic, while the last three look at outbound. Note that in line five we expect to see the server only communicating out on TCP/25. Any other port attempts may indicate the system has been compromised and is now calling home. Obviously it would be a good idea to do the same for the Web server:

grep ‘src 192\.168\.1\.10’ temp3.txt  > web_server_compromise.txt

grep –v ‘src 192\.168\.1\.10’ temp3.txt > temp4.txt

Closing out your script

Now simply repeat this process until you are left with a temp file that has log entries you don’t expect to see. It is now time to start closing out our script. First, rename your last temporary file to something that will catch your attention. On Windows the command would be:

ren temp23.txt interesting_stuff.txt

On Linux or UNIX the command would be:

mv temp23.txt interesting_stuff.txt

This interesting file will probably be the first file you are going to want to review, as it will contain all of the unexpected patterns. Now that all the normal traffic flow is out of the way, it should take substantially less time to spot anything you truly need to worry about.

One nice thing about the temp files is that they can aid in troubleshooting. For example if grep moves 1.5 MB of log entries into a new file, I should expect to see the next temp file shrink by 1.5 MB as well. If not, something is wrong in my script. Also, if you notice that all of your temp files after “temp12.txt” have a zero file length, chances are you have a syntax error just after you created “temp12.txt”.

Once your script is vetted and working however, you may not want to have the temp files in your working directory. That way it is easier to focus in on the sorted files during a review. When you reach this point, simply have the last line of your script delete the temp files. On Windows the syntax would be:

del /q temp*.txt

and on UNIX or Linux the command would be:

rm –f temp*.txt

Automating the process

Once you have a working script, it is now time to automate the process. If you are running Linux or UNIX, simply setup the script to run via cron. If you need help with configuring a cron job there are some excellent help pages. The equivalent on Windows is called a Scheduled Task, and Microsoft has some excellent help in the knowledgebase.

Final thoughts

I mentioned in my last post that I like to look for error packets. I will typically do this right at the beginning of my script. Also, it is not uncommon for systems to call home in order to check for patches. I usually put these exceptions at the beginning of my script as well. Something like:

grep ‘dst 1\.2\.3\.[60-61] ‘ firewall.log > server_patching.txt

grep ‘dst 10\.20\.30\.[1-8] ‘ firewall.log >> server_patching.txt

The first command grabs all traffic headed to 1.2.3.60 or 1.2.3.61. The second looks for traffic headed to 10.20.30.1 – 10.20.30.8. Be very careful in specifying multiple systems! This is a great way to miss something interesting in your log files. You should only use this syntax to describe known patch server. Never specify all the subnets for a particular company. For example if you filter out all Microsoft IPs this way, than a single owned system on their network could control bots on your network and you would never know it.

This syntax is also handy when writing filters for outbound log entries. For example assume that we use 192.168.1.0 – 192.168.1.24 for internal addressing. To grab all outbound HTTP traffic we could say:

grep ‘src 192\.168\.[1-24]\.[0-255] ‘ temp15.txt | grep ‘dst_port 80 ’ > outbound_http.txt

As mentioned in the last post, we may wish to check outbound HTTP during non-business hours to see if we have any Malware calling home.

Don’t forget you can use grep as part of your review process as well. For example let’s say we are reviewing interesting_stuff.txt and spot a source IP (1.2.3.4) we know is hostile. We want to check the file to see if there are any other IP addresses we need to be concerned with. While we could keep paging through the file, a simpler solution would be to use grep:

grep –v 1\.2\.3\.4 interesting_stuff.txt

You review script has the potential to act as a mini-IDS system. By this I mean if you find a suspect pattern but figure out what’s going on, don’t be afraid to leverage your script to categorize this pattern in the future.

For example, let’s say we notice a number of systems on the Internet attempting to access port 5060, but we do not have this port open through our firewall. A quick Google search will tell us that this is SIP (http://en.wikipedia.org/wiki/Session_Initiation_Protocol) traffic. Why bother to look it up every time we see it however if our script can identify it for us? Now that we know 5060 is SIP, simply add the following lines to our script:

grep ‘dst_port 5060 ‘ temp.txt > sip_traffic.txt

We can do the same for any ports that are commonly being probed.

Exec Summary

What makes firewall log review so time consuming is that you need to sift through all of the normal traffic patterns in order to find the log entries that identify a true security issue. By white listing all expected traffic patterns, it becomes far simpler to find and review any unexpected entries within your logs. By further automating the process of sorting the logs, log review can be reduced to a quick activity that can easily be performed on a daily basis.