- Full ICMPv6 support
- Much improved IPv6 support, thanks largely to Daniele Bellucci
- Revamped, more efficient ICMP support (basically copied all the cool things from ICMPv6)
- All encoding/decoding classes moved under their respective layer in Racket::L3, etc.
- Large documentation, test and example improvements
Saturday, November 28, 2009
Racket 1.0.6 Released
Saturday, November 14, 2009
Racket version 1.0.2 released, now in Metasploit
Monday, June 22, 2009
Ubuntu Server on a Soekris
So, this weekend I took a few hours and installed Ubuntu 9.04 (Jaunty Jackalope) Server on one of my trusty Soekris 4801s.
There is plenty of documentation out there that either describes a similar process using significantly older versions of Ubuntu, or involves unnecessarily complicated methods of achieving the same end. Following on a entry I did a few years ago on installing OpenBSD on a Soekris, I once again took the route of using qemu to aid in installation.
OK, lets cut to the chase.
- Download the Ubuntu Server ISO
- Remove the CF or 2.5" disk from your Soekris and plug it in to the system you'll be doing the install on. Take note of what device it gets assigned -- my 2.5" laptop drive got /dev/sdd.
-
Fire up qemu. Change your memory (512), hard disk, and cdrom options as necessary. Note that the -no-acpi option is necessary to get the installer to start:
sudo /usr/bin/qemu -m 512 -boot d -hda '/dev/sdd' -cdrom '~warchild/ubuntu-9.04-server-i386.iso' -net nic,vlan=0 -net user,vlan=0 -localtime -no-acpi
- Install as you normally would.
-
After the install has finished, halt qemu and restart, booting directly off your new Ubuntu installation instead of the ISO:
sudo /usr/bin/qemu -m 512 -hda '/dev/sdd' -net nic,vlan=0 -net user,vlan=0 -localtime -no-acpi
-
Optional: if your Soekris does not support PAE -- the Geode processors used in the 48xx and 45xx certainly do not -- you'll need to install a kernel that does not require PAE. The kernel that ships with Jaunty Server -- 2.6.28-11-server -- requires PAE. You can either recompile and remove that requirement, or take the easy/easier route and just install the generic kernel
sudo apt-get install linux-image-generic
-
Reconfigure the your system to spawn a login shell on the serial port. Put the following in /etc/event.d/ttyS0:
start on runlevel 2 start on runlevel 3 start on runlevel 4 start on runlevel 5 stop on runlevel 0 stop on runlevel 1 stop on runlevel 6 respawn exec /sbin/getty 115200 ttyS0
-
Somewhere towards the top of /boot/grub/menu.lst, ensure that the following two lines are present. The first just configures the serial port (change speed if necessary), and the second configures terminal I/O to be on that serial port:
Next, find the commented out section of /boot/grub/menu.lst that defines defoptions. Leave it commented out, but append the console directive to tie all this serial goodness together:
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 terminal --timeout=5 serial
Now, run update-grub to regenerate menu.lst :# defoptions=splash console=ttyS0,115200
$ sudo update-grub Searching for GRUB installation directory ... found: /boot/grub Searching for default file ... found: /boot/grub/default Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst Searching for splash image ... none found, skipping ... Found kernel: /vmlinuz-2.6.28-13-generic Found kernel: /vmlinuz-2.6.28-11-server Found kernel: /memtest86+.bin Updating /boot/grub/menu.lst ... done $ sudo grep console /boot/grub/menu.lst # defoptions=splash console=ttyS0,115200 # xenkopt=console=tty0 kernel /vmlinuz-2.6.28-13-generic root=UUID=f48b39a6-020d-46e6-b25d-9210472ba1fd ro splash console=ttyS0,115200 kernel /vmlinuz-2.6.28-11-server root=UUID=f48b39a6-020d-46e6-b25d-9210472ba1fd ro splash console=ttyS0,115200
-
As a last step before you boot your Soekris, it probably wouldn't hurt to update:
sudo apt-get update && sudo apt-get -u upgrade
- Halt your Ubuntu host running in qemu, remove the disk and install it in your Soekris
-
Now, configure your Soekris so that it'll jive with the serial settings you just configured in Ubuntu. Unless you have already changed it, your Soekris will (likely) come from the factory with its serial port configured at 9600n81. Configure your favorite serial communication program (minicom) to 9600n81, connect your null-modem serial cable to your Sorkris and host system, and then power on the Soekris. Press ctrl-p to get to the Soekris prompt. Set ConSpeed to 115200 (or whatever you configured your kernel to above):
Now your Soekris will be speaking at 115200, so reconfigure your serial communication program as necessary.
set ConSpeed 115200
- Ensure that the boot order is correct (show BootOrder). If it does not begin with 80 81, 81 80 or something similar, use set BootOrder to remedy that. Remember, 80 is the CF, 81 is the first IDE device if present.
- Type 'boot'
- Enjoy.
Monday, January 26, 2009
Name-based Virtual Hosting and Web Application Security
Over the past several weeks I've had the privilege of beginning evaluations of the best that the commercial security sector has to offer in the realm of web application security auditing. Arguments about whether simply buying a web application security firewall or pursuing this initiative from a code auditing point of view instead aside, the offerings from the top names in this space run the gamut from extremely impressive to downright depressing.
For purposes of this post, I am just focusing on the tools out there that do your traditional blackbox based approach to auditing. Given an IP address or a URL and some other minimal hand-holding, nearly all of the big names in this arena will do fairly good job of identifying the bulk of the "low hanging fruit."
Being the studious and meticulous geek that I am, one of my first requirements when evaluating these products was that they properly support the auditing of web applications that live on a host utilizing named-based virtual hosting. Simple, right? RFC2616 makes this sort of thing very clear and one would expect that not only would tools currently available be able to employ this knowledge to further leverage their way into a web application, but when asked about these features a given vendor would understand how they are useful. Needless to say, the HTTP/1.1 "Host" header plays a pretty important role on the majority of modern websites.
Well, I hate to break it to you, folks, but this is sadly not the case. Of all the vendors on the market, not a single one fully supports this functionality. Yes, you read that right -- no vendor in the blackbox web application security auditing space truly supports HTTP/1.1's "Host" header.
Pausing here for a second, I can sense the heated emails and comments aimed in my general direction. Please, hear me out.
So, just a hint of background. Many products utilize readily available HTTP client libraries written in their language of choice; rightfully so -- why reinvent the wheel! At least one even manipulates IE or Firefox directly to do their bidding, which I find particularly interesting.
And this is where the problem starts to manifest itself. When a human being makes a web request using a browser, they typically enter the address either using an IP address or a host name of some manner. Under the hood, as many of us know, the host name (if present) is resolved and the IP address that results is used as the destination address of the network socket. Once this connection is established using a modern browser, the host name (and port!) from the original URL is sent along as part of the request in the "Host" header of an HTTP/1.1 request. Simple, right? This allows a number of 1999-esque features such as being able to host more than one website on a single IP address or do fun SEO things like determining what URL a visitor originally used to arrive on your property.
Whats the big problem, right? Of course, all vendors that I've dealt with properly support sending HTTP/1.1 requests with a "Host" header, but they don't exploit all of its beauties. Imagine the following two situations.
One. Imagine two hosts: 192.168.0.1 (PRODUCTION) and 192.168.0.2 (TEST). Both PRODUCTION and TEST webservers contain name-based virtual hosts for www.example.com and seoftw.example.com. DNS for www.example.com and seoftw.example.com point to 192.168.0.1. How do you audit TEST accurately and completely? The obvious and hacky answer that most vendors gave was to diddle DNS before each audit so that the host performing the audit can correctly resolve the target host names to the IP addresses of the particular environment (PRODUCTION or TEST) that you are attempting to audit. If that was your answer, please hold while I drop the >$200k some of these tools cost for a single user into a bag and thwap some sense into you.
Two. Same two hosts as above, but toss a couple dozen other named-based virtual hosts, years of HTTP configurations gone wrong and a little luck into the mix, and you just might hit the proverbial pay-dirt if you grok the Host header. All manner of fun things can be discovered if you play around with it, such as:
- Other virtual hosts that you might not have known about. Hint: send a 1.1 request with an invalid Host header.
- Previously "protected" areas of the website now exposed by accessing it using a different Host header
Much like many of my other ideas which come while sleeping or in other prominent thinking spots, I've decided to whack together some code to explore these things more. The resulting abomination is vhinfo, which given a URL and/or an IP address will play around with various HTTP/1.1 Host headers and see what other VHOSTs it can find based on information that the server provides or is otherwise freely available. Like I said, its gross, partially unfinished and needs cleanup, but the results are fun:
Looks like Facebook really likes to strip the first portion of the hostname out and replace it with a 'www'.
$ vhinfo www.facebook.com HTTP/1.1 Host: www.facebook.com on 69.63.176.140 -> 200: OK HTTP/1.0 on 69.63.176.140 -> HTTP/1.1 200 OK () HTTP/1.0 www.facebook.com on 69.63.176.140 -> HTTP/1.1 302 Found (http://www.facebook.com/common/browser.php) HTTP/1.1 Host: 69.63.176.140 on 69.63.176.140 -> 200: OK HTTP/1.0 on 69.63.176.140 -> HTTP/1.1 200 OK () HTTP/1.0 69.63.176.140 on 69.63.176.140 -> HTTP/1.1 302 Found (http://www.63.176.140/common/browser.php) HTTP/1.1 Host: localhost on 69.63.176.140 -> 200: OK HTTP/1.0 on 69.63.176.140 -> HTTP/1.1 200 OK () HTTP/1.0 localhost on 69.63.176.140 -> HTTP/1.1 302 Found (http://www.ocalhost/common/browser.php) HTTP/1.1 Host: 127.0.0.1 on 69.63.176.140 -> 200: OK HTTP/1.0 on 69.63.176.140 -> HTTP/1.1 200 OK () HTTP/1.0 127.0.0.1 on 69.63.176.140 -> HTTP/1.1 302 Found (http://www.0.0.1/common/browser.php) HTTP/1.1 Host: www.04.05.sf2p.facebook.com on 69.63.176.140 -> 200: OK HTTP/1.0 on 69.63.176.140 -> HTTP/1.1 200 OK () HTTP/1.0 www.04.05.sf2p.facebook.com on 69.63.176.140 -> HTTP/1.1 302 Found (http://www.04.05.sf2p.facebook.com/common/browser.php)
Sun likes to throw 500's on certain virtual hosts (these should probably actually be 404's):
$ vhinfo www.sun.com HTTP/1.1 Host: www.sun.com on 72.5.124.61 -> 200: OK HTTP/1.0 on 72.5.124.61 -> HTTP/1.1 200 OK HTTP/1.0 www.sun.com on 72.5.124.61 -> HTTP/1.1 200 OK HTTP/1.1 Host: 72.5.124.61 on 72.5.124.61 -> 200: OK HTTP/1.0 on 72.5.124.61 -> HTTP/1.1 200 OK HTTP/1.0 72.5.124.61 on 72.5.124.61 -> HTTP/1.1 200 OK HTTP/1.1 Host: localhost on 72.5.124.61 -> 500: Server Error HTTP/1.0 on 72.5.124.61 -> HTTP/1.1 200 OK HTTP/1.0 localhost on 72.5.124.61 -> HTTP/1.1 500 Server Error HTTP/1.1 Host: 127.0.0.1 on 72.5.124.61 -> 500: Server Error HTTP/1.0 on 72.5.124.61 -> HTTP/1.1 200 OK HTTP/1.0 127.0.0.1 on 72.5.124.61 -> HTTP/1.1 500 Server Error
And Yahoo, not to be outdone, throws standards to the wind and just returns raw HTML text sans HTTP response headers (and breaks my code :().
$ vhinfo yahoo.com HTTP/1.1 Host: yahoo.com on 206.190.60.37 -> 301: Moved Permanently (http://www.yahoo.com/) HTTP/1.1 Host: www.yahoo.com on 206.190.60.37 -> 301: Moved Permanently (http://www.yahoo.akadns.net/) Connection to http://206.190.60.37/ failed! -- wrong status line: "<!doctype html public \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">" /home/warchild/bin/vhinfo:128:in `check': undefined method `[]' for nil:NilClass (NoMethodError)
In summary, the HTTP/1.1 "Host" header is an important part of accurately and completely performing web application security audits and has a role in any vulnerability assessment that is definitely worth considering.
Friday, January 2, 2009
Hawler, the Ruby crawler, 0.3 released
Since it has been several months since I've had to do anything to Hawler, I figured this was a good time to go in an do some much needed cleanup and improvements. Chief among the changes are:
- Proxy support ("-P [IP:PORT]")
- Documentation cleanup
- Support crawling frame and form tags
- Add a useful default banner to calling scripts if none provided
- Print out defaults when help is called
Thanks to ET for his proxy contributions.
As usual, the following will get you up and running with Hawler:
gem install --source http://spoofed.org/files/hawler/ hawler
Using Hawler? Comments? Complaints? Suggestions? Drop me a line - I'd like to hear it.
Monday, December 22, 2008
Cisco AnyConnect 2.x Local Privilege Escalation
Exploit code for Linux and Macintosh platforms is available, however the code is in an unknown state. At one point I had attempted to unify the code so that it would work regardless of where it was run, however I never got much further than the thought. Since I cannot validate the exploit code any further, the code is being release "as is".
There are three vulnerabilities on both platforms and the exploit techniques are similar if not identical.
Vulnerability #1: /tmp/routechangesv4.bin is written mode 666 (world readable and writable) every time AnyConnect is launched. Because it is never executed directly by AnyConnect, we must use its world writable goodness to achieve our goal. In this case, a simple symlink-attack to create a world-writable crontab for root into which we inject our commands is any easy approach.
Vulnerability #2: The /tmp/Temp8-Vpn2e8 directory used as part of the Java applet is not checked for existence prior to use and, since there is no randomness in the name, is easily tricked into utilizing our maliciously placed executables. When the Java applet runs, it creates and uses /tmp/Temp8-Vpn2e8 to drop vpndownloader.sh, which in turn (you guessed it!) downloads the remainder of the files needed to utilize the VPN. Exploitation is relatively straight forward -- create /tmp/Temp8-Vpn2e8 with permissions that we control, wait for vpndownloader.sh to be placed by the applet and then swap it out with our payload prior to the applet executing it.
Vulnerability #3: /tmp/vpn-uninstall.log is written mode 666, but I cannot recall if this happens only install, uninstall or at every launch. Exploit method is identical to the first vulnerability.
Thanks to Cisco's PSIRT for their help in getting these issues addressed.
Monday, July 14, 2008
Mitigating DNS cache poisoning with PF
By now, nearly everyone has heard about the latest round of DNS vulnerabilities, including non-technical people given the massive media coverage. If you have not heard of it, you probably wouldn't be reading this, however on the off chance that I am wrong, please read US-CERT VU#800113 and CVE-2008-1447 and then continue here. Most organizations are scrambling to find and apply fixes while some are still sitting idly debating the merits of the find.
There is nothing to debate. This is, in my opinion, an epic find. Because DNS is (in most cases) based on UDP (connectionless), the "security" is based on a handful of characteristics. Other flaws aside, a proper DNS client will only accept DNS responses that have the following characteristics:
- The response contains an answer to a question that the client asked
- The response came from a nameserver that the client originally initiated the request to
- The TXID of the response matches that of the request
- The destination port of the response matches the source port of the original request
Dan's find, of which the full details are being withheld until BlackHat 2008 this August, nearly eliminates the source port difficulty and likely also tackles or at least reduces the problem space of the TXID issue. I have to be honest here -- anyone who didn't notice this particular anomaly in the past should be embarrassed -- I know I am. If you were to view the state table of a firewall fronting a vulnerable DNS implementation, you'd see that the source port of all outbound DNS requests from that particular DNS implementation would be fixed for an inordinately long time:
sis0 udp a.b.c.d:6489 -> 192.58.128.30:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 192.35.51.30:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 144.142.2.6:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 199.7.83.42:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 192.12.94.30:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 192.153.156.3:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 204.2.178.133:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 192.33.4.12:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 204.74.113.1:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:6489 -> 61.200.81.111:53 SINGLE:NO_TRAFFIC sis0 udp a.b.c.d:6489 -> 207.252.96.3:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 163.192.1.10:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 192.31.80.30:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 216.239.38.10:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 216.239.34.10:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 64.233.167.9:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 66.249.93.9:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 64.233.161.9:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:6489 -> 206.132.100.105:53 SINGLE:NO_TRAFFIC
As you can see, the source port is identical for all outbound DNS requests. This port will change eventually, and honestly I am not sure what the exact details are regarding its change, however I believe it is sufficient to say that it remains constant long enough for you to be concerned with it.
In addition to my work related duties, I also have my own personal systems to worry about. My client systems were quickly fixed, however they remain vulnerable because of my setup -- all DNS requests from my network are forced to go through an internal DNS server that I control. I use OpenBSD almost exclusively for my routing, firewalling and other common "gateway" type functionality, and it just so happens that my DNS server runs OpenBSD too. So despite my clients being secure from this attack if they were querying external nameservers directly, my internal DNS server put them at risk. I was surprised to find that on the US-CERT announcement that they were listed as "unknown" and now, more than a week later, there is still no mention of the issue on any of the OpenBSD mailing lists or on the website.
Since my DNS server runs on a little, low-power device, the thought of having to rebuild something from source or other disk/CPU intensive operations makes me cringe. Thats what got me thinking -- is there a way I can protect myself until a patch is available from my vendor and I have time to deal with it?
As it turns out, I believe there is. My interim solution is to use PF to provide some randomization to my outbound DNS requests.
If your DNS server sits behind a NATing PF device, the source port randomization is implicit -- see the section titled TRANSLATION in the pf.conf manpage. If your DNS server is also running on the PF device, as it is in my case, you are still vulnerable unless you configure things correctly.
The trick is to force requests coming from your DNS server, which have non-random source ports, to be processed by PF so that they too are subject to the implicit source port randomization. This is actually quite simple, and you may already be doing this without realizing it, depending on your setup. Assuming the outbound address of your DNS server (or PF device itself) is a.b.c.d, the following NAT entry in your pf.conf should be sufficient:
nat on $WAN_IF inet proto { tcp, udp } from a.b.c.d to any port 53 -> a.b.c.d
This results in a dramatically different state table:
sis0 udp a.b.c.d:40783 -> a.b.c.d:59623 -> 192.55.83.30:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:64916 -> 199.7.83.42:53 MULTIPLE:MULTIPLE sis0 udp a.b.c.d:40783 -> a.b.c.d:50591 -> 202.12.28.131:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:60017 -> 192.55.83.30:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:63472 -> 200.160.0.7:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:55603 -> 200.189.40.10:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:50749 -> 192.52.178.30:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:64190 -> 192.83.166.11:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:64346 -> 128.63.2.53:53 MULTIPLE:SINGLE sis0 udp a.b.c.d:40783 -> a.b.c.d:59970 -> 61.220.48.1:53 SINGLE:NO_TRAFFIC
As you can see, the original source port is still fixed in the internal table, however the source port that is used out there on the big bad Internet, where the risk lies, is random. To add even further randomness, if you have multiple addresses at your disposal, you can distribute outbound DNS requests across a pool of those addresses:
nat on $WAN_IF inet proto { tcp, udp } from a.b.c.d to any port 53 -> { a.b.c.1, a.b.c.2, a.b.c.3, ... } round-robin
# or if you have a contiguous space available, use the 'random' modifier
nat on $WAN_IF inet proto { tcp, udp } from a.b.c.d. to any port 53 -> { somenetwork/mask } random
The astute reader will have probably already noticed that it is major overkill to include TCP DNS traffic in these countermeasures, however I cannot think of any adverse side effects of doing so.
The proof is in the pudding. Utilizing the handy service setup by DNS-OARC, you can see that my setup appears "FAIR":
$ dig +short porttest.dns-oarc.net TXT z.y.x.w.v.u.t.s.r.q.p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a.pt.dns-oarc.net. "a.b.c.d is FAIR: 14 queries in 10598.6 seconds from 14 ports with std dev 4249.80"
