I Smell Packets


SANS SEC567: Power Packet Crafting with Scapy Debut at Sacramento!
October 22, 2009, 2:34 pm
Filed under: SANS, scapy

I have the opportunity to teach the brand new SANS SEC567: Power Packet Crafting with Scapy course!

If you’re not familiar with Scapy, Scapy is an unbelievably powerful tool that you can use to create all sorts of different packets. If you’ve ever needed to test an IDS/IPS rule, check weather or not a firewall will block something, or test some application to see how it reacts to certain traffic (like for a penetration test for example) Scapy can make your job easier.

The course was written by Judy Novak who used to work for Sourcefire. While at Sourcefire, Judy was responsible for testing IDS/IPS solutions and used Scapy extensively for doing so. She does an excellent job of explaining everything from basics to even the more advanced techniques. The course is jammed packed full of exercises. By the end of the day I can assure you that you will be able to craft some pretty awesome packets.

This course will be having it’s debut in Sacramento. Since this is a debut, you have the opportunity to take the course for half price! How’s that for a bargain? In return, all we ask is that you provide us with some feedback.

If you’d like more information or if you’d like to sign-up, please follow the link below:

SANS: SEC567 Power Packet Crafting with Scapy Debut at Sacramento – Power Packet Crafting with Scapy

Advertisements


Solution to ‘What’s wrong with Smelly Widgets?’
October 20, 2009, 2:39 pm
Filed under: Packet Challenge, SANS, SQL injection, Wireshark

The winner of the “What’s wrong with Smelly Widgets packet challenge?” is . . . Arvind Doraiswamy.

Here’s Arvind’s solution.

Arvind writes:

1. A blank form with a login and a password is first displayed. The webserver is running on 192.168.94.143 and an access attempt is made from 192.168.94.144.

2. Attempt at logging in with a blank username and password is then done(Packet 9). This is insuccessful as shown in Packet 12 where a user is not allowed to login with empty credentials.

3. Packet 14 sees the user try to login with the username chris and an empty password. This too is insuccessful as shown in Packet 17 , a user must have something in the password field.

4. Packet 19 sees a third attempt at trying to login with the username chris and the password “password” . The attacker is trying out various common password combinations. This too is insuccessful as shown in Packet 22 and returns an error message of “Invalid credentials” . This means that you must enter something in both fields. So the attacker must now either find a valid combination or must try and bypass the login somehow. Well, he doesn’t have a valid combination so he decides on the latter.

5. At this point though there is another request for the home page on 192.168.94.143 from 192.168.94.1. He tries to login with the username of chris and a password of smellywidgets. This results in a successful login and displays order history. This is crucial…

6. On packet 37 we now see chris making another attempt to unsuccessfully login with username chris and password ismellpackets from the IP 192.168.94.144. This again is unsuccessful.

7. The attacker on 192.168.94.144 is now fed up and decides to try and get in without a valid username and password. On packet 42 he sends a request with username and password as follows:
username: ‘ OR 1=1–
passsword: password

This login is a success!! What happened here? Lets take a look at how a normal successful login would happen in the first place.

EXPLANATION:

A website is hosted on a webserver. A login page is part of the website. When a user enters his username and password on the website, it is accepted as input by the website form and handed over to the code for further processing. The application code now must compare what the user entered with what is already stored in the database. If it didn’t do this — well , there wouldn’t be a need for a login form at all and everyone could see everyone’s data. Now how does the application actually do this?

The application needs to ask the database whether it has entries for the input that the user gave at the login page. So if we take the example of a successful login made by chris from the IP 192.168.94.1 the application will ask the DB – “Do you have an entry for someone called chris , he’s entered a password called smellywidgets. Is this correct?” . The DB checks in its entries and says “yes that’s fine.. Chris indeed exists – allow him in”. Now the language that the application talks to the DB is called SQL – and when it asks a question – its said to be “querying” the database. So effectively the application queries the database in a language called SQL.

Now obviously there needs to be some structure to this SQL query. So while checking authentication is sends a query as follows:
SELECT username from users where ‘username’=’chris’ and ‘password’=’smellywidgets’ . SQL surrounds its userinput by single quotes, that’s part of the syntax.

The DB check the validity of the user chris , checks if his password is smellywidgets and then if it finds an entry like that, returns the username to the application. The application checks if the number of entries returned are not 0 (meaning there was a match) and then allows the user access. Great..now we know how a normal login happens. Now what happened when we typed ‘ OR 1=1– instead of chris? Again an SQL query is formed , but this time the query is as follows:
SELECT username from users where ‘username’=” OR 1=1– and ‘password’=’password’

Pay careful attention to the ” OR 1=1– . It effectively translates to .. “Please check is there is a user called ” (BLANK) OR check if 1=1 “. Huh? Now obviously there is no user called ” or BLANK in the DB but the second part 1=1 .. well that’s always going to be true ..right? 1 is always 1 and 2 is always 2 so that part will alwys be true. This means that the first part of checking the username has evaluated to TRUE and a successful message will be returned if the password is correct as well. Er..but I don’t know the password. No problem .. that’s where the — comes along.

A — in SQL means a comment , which means everything after the — is ignored by the DB engine thus resulting in the query which runs as :
SELECT username from users where ‘username’=” OR 1=1–

It didn’t matter what password I entered, the DB just checked if 1=1 which is always TRUE, returned a message to the app saying.. hey this is TRUE. Go ahead and grant access, and the application duly did so. This technique is called SQL Injection where you modify a backend SQL query using your own input and retrieve data accordingly. Now back to the challenge!!

—–

8. Packet 51 depicts a login successful message to the SQL injection request made on packet 42. Packet 53 shows each and every widget order that was placed by every user, this is clear because multiple credit card numbers are shown in the HTTP response. This has happened because the DB has returned the first entry which it found matched the user’s request – and this was the first user , who in this case was probably an admin user who could see all entries.

9.On packet 68 the user clicks the logout button and decides to logout of the application. Confirmation of his successful logout is shown in Packet 77 and 79.

10. The attacker starts another login process in Packet 81. The body of the HTTP POST request is split across so many packets because of the size of the __VIEWSTATE parameter which ASPX applications use to remember previous entries made by users in forms. This isn’t that relevant here though as of now. The request is so huge that you see the actual userinput only in packet 86 this time. This time the entry he has made is %27%3B+UPDATE+Orders+Set+Amount%3D0.01– . What does this mean now? Time for a little bit of background on what those funny characters are:
—-

EXPLANATION:
When you type a special character which isn’t alphanumeric the browser performs something called URL Encoding on it before sending it to the server. It effectively means – When you send data over the Internet , it doesn’t need to be encoded if its ASCII.. coz ASCII is an example of “WYSIWYG” (What you see is what you get). However that isn’t true of other characters like ‘ % and others – hence they are URL encoded before sending it out. A single space is encoded as %20 by the browser – hence if there’s a space in your data you must send it as a + instead. Now back to the challenge, what does this input say?
—-

11. %27%3B+UPDATE+Orders+Set+Amount%3D0.01– translates to ‘; UPDATE Orders Set Amount=0.01– . Hmm ..things are getting interesting now. If you recall how we discussed SQL before – the backend query for this translates to: SELECT username from users where ‘username’=”; UPDATE Orders Set Amount=0.01– and ‘password’=’password’ . This tells the DB to check if the username is blank and the update all entries in the Amount column in the Orders table to 0.01. Now note …this isn’t going to successfully log you in to the DB – we don’t have a 1=1 like before but the SQL query will still work. Why? Because we know that the username field is vulnerable to SQL Injection I can not only log in by bypassing authentication — I can tell the application to send any query I want executed on the remote DB. In this case its an update query — I separate the original SELECT query and the UPDATE query with a ; — The UPDATE query won’t run unless you put the ; — That’s a separator incase you want to run multiple queries (batched queries they are called in SQL). Potentially I could run more queries by just putting in a ; between each of them. Phew ..lets move on.

12. Packet 98 – shows a failed login attempt for the UPDATE query..but that’s perfectly fine. You do not need to be “logged in” to do damage with a SQL injection. All you need is an entry point. That’s why its so dangerous. Going on then..

13. Now he tries to login with the ‘ OR 1=1– input which we discussed earlier..possibly to check whether what he did with the UPDATE succeeded or not. The complete Request body is in Packet 105.

14. Perfect!! Look at Packet 121 now.. You need to look directly at 121 because Wirshark has this feature called Reassembled TCP where it basically joins all the data split across packets into 1 long bit. if you don’t want to read inside Wireshark , you can right click paket 121 in Wireshark and do a Copy — Bytes Printable text only to a text editor. You can also copy from a FollowTCPStream. Here you can clearly see that the amounts of each and every widget is now 0.01 , meaning that the UPDATE query succeeded.. even without a successful login.

15. Packet 129 sees the attacker logout again..now that he’s confirmed that the SQL Injection has worked and Packet 140 shows him the login page again.

16. Things are now getting worse on Packet 147. By following the same methodology above you can see that the payload the attacker uses this time is:
INSERT INTO Users VALUES (100,’hacker’,’sniffthis’)– . He’s creating a new user with an ID of 100 a username of hackers and a password sniffthis. Again..the SQL will succeed..but he won’t be able to login. This shows that the ‘ OR 1=1– was primarily just a test to find out whether the field was vulnerable or not, the real juicy stuff is here. The hacker should now try and login with this new account..lets see if this happens. Packet 159 BTW predictably rejects the login attempt.

17. Yes, predictable the hacker now logs in with the username of hacker and the password of sniffthis in Packet 166 and Packet 170 shows a successful response. After the test login he logs out again on Packet 172.

18. Now he starts SQL injecting again this time using a batched SQL query (remember queries split by a ; ? ) to log in successfully with a ‘ OR 1=1– as well as add a new entry with the query :
‘ OR 1=1; INSERT INTO Orders (OrderId, Item, CreditCard) SELECT UserId,Username,Password FROM users–

Now there should be a new entry in the Orders table with the values 100,hacker,sniffthis .. right at the bottom. We’ve basically retrieved the hacker’s details from the users table and Inserted them into the orders table for some reasson. Lets see why..lets look at the response.

19. Yes , just like we thought. Have a look right at the bottom of Packet 206. We see a row 100 hacker sniffthis ; meaning that the attacker managed to successfully INSERT and VIEW his results. He then successfully logs out as can be seen in Packet 236. Now what?

20. He’s placed an entry into Orders , meaning he bought stuff without paying a cent, he’s changed all order prices , now he destroys the entire users table by SQL injecting again — ‘; drop table users– . This is on Packet 248. The by now familiar Invalid Credentials message comes in on packet 266… but he’s not bothered any more. His job is done.

21. Now there’s a connection again from the other IP 192.168.94.1 . Remember the guy here successfully logged in once? Lets see what happens now. Yes, he tries again on Packet 276 with the same username and password with which he succeeded last time – Username: chris and Password: smellywidgets.

22. Disaster.. The Users table is not found…of course it won’t be – The ‘hacker’ user dropped it after he inserted a successful order. The response in packet 279 shows this error message clearly – ERROR: Failed to execute SQL command: Invalid object name ‘Users’

Maybe there will be guys who use clever scripting techniques to pull out all the data – but since the dump was just 280 packets I didn’t really spend too much time thinking on how I’d do that and stuck to good old Wireshark instead. Thnx for a nice challenge anyway though 🙂

Chris continues:

About the only thing I’d like to add to Arvind’s solution is that it’s sometimes nice to know what type of systems you’re dealing with. In this particular case, you can do this by following the TCP Stream and looking at Host Headers. Notice bold text in the following output:

GET / HTTP/1.1
Host: http://www.smellywidgets.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Ubuntu/8.10 (intrepid) Firefox/3.0.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Mon, 05 Oct 2009 17:51:57 GMT
Content-Length: 1922

Examining the above, we can see that this server appears to be running IIS 7 and ASP.NET. We can probably safely assume that this is a Windows 2008 server. Now, just because this is a new Windows 2008 server doesn’t mean that it’s immune to SQL injection. User input always needs to be sanitized. Filtering out characters like single quotes, double quotes, and semi-colons would have prevented this attack.

Just case you’re interested, this challenge was created using a Windows 2008 virtual machine, IIS, ASP.NET, Visual Web Developer 2008 Express, and SQL Server Express 2008.

Thanks to everyone for sending in all the write-ups. You all did a great job. It was really hard to choose a winner. Special shot out to Louw Smith for being the only one to mention the Beatles reference. It was also nice to have a couple of my former Sec 401:SANS Security Essentials students submit answers. You guys rock!

Speaking of Sec 401: SANS Security Essentials, I’ll be teaching it again in Sacramento, CA. January 28-30 and February 1-3. If you’re interested in attending please feel free to contact me. There are also some links on the left with more information.

That’s it for now. Again, congratulations to Arvind and thanks to everyone who sent in answers.

The following are some links to more information about this week’s challenge:

SecuriTeam – SQL Injection Walkthrough
SQL Injection Cheat Sheet
Cheat Sheets – pentestmonkey.net



Packet Challenge
May 6, 2009, 11:57 pm
Filed under: hping, Intrusion Detection In-Depth, Packet Challenge, SANS, tcpdump

Earlier today I tweeted an easy little packet challenge. The challenge for me was keeping that packet to less than 140 characters. Here is a short description of how I created the challenge:

First, I created the payload for the packet. I did this by placing some text in a file using the following command:

echo 1st2DMmegetsAStarbuckscard > payload.txt

Next, I used a tool called Hping to craft the packet:

hping3 –icmp –file payload.txt –data 26 127.0.0.1

In the above command, the –icmp instructs hping to create an ICMP packet. The –file option specifies a file to be used as the payload. Next, the –data option tells hping how many bytes of data in the payload. In this case, it’s 26 bytes data. Finally there is the destination IP address which is 127.0.0.1.

To capture the packet, I ran a sniffer called tcpdump:

tcpdump -i lo0 -X -s0

Here is packet in HEX:

4500 0036 308b 0000 4001 0000 7f00 0001 7f00 0001 0800 89f3 5a27 0200 3173 7432 444d 6d65 6765 7473 4153 7461 7262 7563 6b73 6361 7264

Decoding the Packet

Here is quick run though of how to decode the packet. First of all, when decoding packets it’s often helpful to have a reference. Here is a link to the SANS website where you can download the TCP/IP Pocket Reference from. I call this the cheat sheet.

There are also a couple of other points to remember:

1. Every two HEX characters equals one byte.

2. Start counting with 0.

Starting with byte 0, there is 45. Highlighted below:

4500 0036 308b 0000 4001 0000 7f00 0001 7f00 0001 0800 89f3 5a27 0200 3173 7432 444d 6d65 6765 7473 4153 7461 7262 7563 6b73 6361 7264

Find the IP header section on the cheat sheet. Notice that in byte 0 we find the IP Version Number and the IP Header Length fields. The 4 in the IP Version Number field means is an IP Version 4 packet. The next field, the IP Header Length, there is a 5. This represents 32-bit words. So, in order to calculate the IP Header Length we need to multiply this field by 4. 5*4=20. Therefore, the IP Header length is 20 bytes.

Next count 20 bytes. Remember, every two HEX characters equals one byte and start counting at 0.

4500 0036 308b 0000 4001 0000 7f00 0001 7f00 0001 0800 89f3 5a27 0200 3173 7432 444d 6d65 6765 7473 4153 7461 7262 7563 6b73 6361 7264

The portion highlighted above is the IP Header. What comes next? To find out look at the Protocol Field of the IP Header. According to the cheat sheet the Protocol Field is found in byte 9 of the IP Header. Looking back at the packet, there is a 01 in there:

4500 0036 308b 0000 4001 0000 7f00 0001 7f00 0001 0800 89f3 5a27 0200 3173 7432 444d 6d65 6765 7473 4153 7461 7262 7563 6b73 6361 7264

Referring back to the cheat sheet, a 1 in the Protocol Field of the IP Header means that the next protocol is going to be ICMP. Remember that when I created this packet I specified ICMP, so this is what one would expect here. Now the ICMP part of the packet. The IP Header Length was 20 bytes, after that begins the ICMP protocol portion. This is highlighted below:

4500 0036 308b 0000 4001 0000 7f00 0001 7f00 0001 0800 89f3 5a27 0200 3173 7432 444d 6d65 6765 7473 4153 7461 7262 7563 6b73 6361 7264

To decode this portion of the packet look at the ICMP Header section of the cheat sheet. The first couple of bytes of the ICMP Header are the Type and Code fields. There is a 0800 in those fields, meaning, referring back to the cheat sheet that this is an ICMP Echo or a PING.

Since it’s a PING, drop down to the Ping section of the cheat sheet and locate the Data section of the ICMP Echo. This Data should contain the text in the payload.txt file. Here is the Data section highlighted:

4500 0036 308b 0000 4001 0000 7f00 0001 7f00 0001 0800 89f3 5a27 0200 3173 7432 444d 6d65 6765 7473 4153 7461 7262 7563 6b73 6361 7264


These bytes fall into the ASCII printable range, so convent it to ASCII.

31 73 74 32 44 4d 6d 65 67 65 74 73 41 53 74 61 72 62 75 63 6b 73 63 61 72 64
1 s t 2 D M m e g e t s A S t a r b u c k s c a r d

This is just a brief explanation. It may seem like a lot of work, but it’s really not that difficult. Like most other things it takes a little practice. Some people can even do this in their sleep, I assure you I’m not one of those people.

Another thing that someone could have done was just to look for that HEX that falls into the ASCII printable range. They would’ve immediately focused in on the payload. Maybe I’ll use some double XOR encryption next time to make it harder. 😉

One of my favorite courses is the SANS Security 503: Intrusion Detection In-Depth course. In that course you get to spend 6 days learning all about TCP/IP and performing traffic analysis. There are a ton of hands-on exercises. And unlike other courses that may teach networking and TCP/IP, in this course you get to learn this stuff from an attackers perspective.

Congratulations to @quine for being the first to send me a message and winning the Starbucks Card. It’s on the way.