Wednesday, July 15, 2009

Simple Hacking on Cisco WCS for Seamless Anonymous Browsing

My university has a Cisco network, which has all sorts of nice management features such as a wireless control system (WCS), vlans, CleanAccess, and I'm sure many more goodies. The wireless network broadcasts two SSIDs: one is for people associated with the university, requires credentials, and puts you in the appropriate vlan, the other is for visitors and provides completely anonymous access. The visitor network requires you to click a button to accept some University policy before you gain access, and this annoying redirect is reset every 6 hours or so. This is particularly cumbersome because if I open Firefox before accepting the policy then it redirects every saved tab to the policy page, and then to the university homepage.

I use the visitor network for various reasons, one is that because of some ridiculous network policies from the student vlan I can't get to some ports (svn, rdp, etc) on the DMZ vlan where I have a couple servers, despite the fact that 99% of the internet can access those ports. I think this is being fixed, but until then I need to use the visitor network. Also, I believe anonymous access to the internet is critical, but I am going to refrain from philosophical/political rants on a technical blog.

Just to procrastinate real work I decided to attempt to automate the policy accept process, and thus save my Firefox tabs.

I started by taking look at the policy page html and javascript, but it was a bit obtruse, so I went ahead and installed Firebug and took a look at its "Net" tab. Unfortunately since the policy page uses 20 gazillion different redirects, it kept changing pages before I could see what it was sending. (If anyone knows a workaround for this please let me know; I tried enabling redirect warnings in the Firefox preferences, but it didn't help.)

So I changed my hosts file to point wirelessauth.university.edu to 127.0.0.1, and fired up netcat. Turns out the policy page was accessing wirelessauth over ssl, so netcat was kind of useless. This also meant packet sniffers would be useless... So I just installed apache w/ ssl. This worked like a charm and I was able to use Firebug to see that it was POSTing some stuff to https://wirelesssauth.university.edu/login.html:

POST /login.html HTTP/1.1
Host: wirelessauth.university.edu
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.8) Gecko/20090331
00 Ubuntu/9.04 (jaunty) Firefox/3.0.8
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
Referer: http://www.university.edu/it/network/visitor_wireless/?switch_url=https://wirelessauth.university.edu/login.html&ap_mac=00:0b:85:7f:26:40&wlan=Visitor&redirect=woot.com/
Cookie: __utma=64401068.180182089960766140.1247531434.1247531434.1247531434.1; __utmz=64401068.1247531434.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=64401068

buttonClicked=4&err_flag=0&err_msg=&info_flag=0&info_msg=&redirect_url=


Notably it is sending all sorts of crap: cookies, host, referrer, url encoded values, etc. I replicated everything except for the cookies and used wget to send a login request. This worked just fine:

wget --post-data="buttonClicked=4&err_flag=0&err_msg=&info_flag=0&info_msg=&redirect_url=" --user-agent="Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.8) Gecko/2009033100 Ubuntu/9.04 (jaunty) Firefox/3.0.8" --referer="http://www.university.edu/it/network/visitor_wireless/?switch_url=https://wirelessauth.university.edu/login.html&ap_mac=00:0b:85:7f:26:40&wlan=Visitor&redirect=woot.com/" http://wirelessauth.university.edu/login.html


Turns out all you really need is:

wget --post-data="buttonClicked=4" https://wirelessauth.university.edu/login.html

Which is easy enough to remember :)


I did leave out one little detail... that is how I was able to play with the policy/login page without having to wait 6 hours for it to timeout. This is obvious for network guys, just disassociate from the wifi network and change your MAC address:

sudo ifconfig wlan0 down
sudo ifconfig wlan0 hw ether ##:##:##:##:##:##
sudo ifconfig wlan0 up


While disconnecting and forgetting a network in NetworkManager is relatively easy:

gconftool-2 --recursive-unset /system/networking/connections/1

I haven't figured out an easy way to add a connection from the cli. It is pretty simple to associate to a wifi network with other command line tools, but I would like to go through gconf/NetworkManager. This code snippet just removes the first remembered connection, there is probably a relatively easy way to do it by name too.

Since I'm on an anonymous wireless network (and booting from a livecd for that matter) it would be nice to have a random MAC address too. Putting it all together:

#!/bin/bash

gconftool-2 --recursive-unset /system/networking/connections/1

sudo ifconfig wlan0 down

#randomize... Almost all legite MACs start with 00
eth=00
for i in `seq 1 5`; do
eth=$eth:`head -c1 /dev/random |hexdump -e '1 "%x"'`
done
sudo ifconfig wlan0 hw ether $eth
sudo ifconfig wlan0 up

#need code to join network... for now just click, then do the wget manually
#wget --post-data="buttonClicked=4" https://wirelessauth.university.edu/login.html


After concocting my random MAC address generator I realized somebody else probably already did it. Sure enough here is one of the first hits. I like my method better because it actually uses the appropriate random number generator, not /proc/interrupts. That example leaves off the first byte, which should be 0. Both because most legitimate MAC addresses start with 00, and the 7th and 8th bits signify multi/unicast and global/local uniqueness. Granted you could probably just do:

MAC=00:`head /dev/urandom|md5sum| sed -r 's/^(.{10}).*$/\1/; s/([0-9a-f]{2})/\1:/g; s/:$//;'`

or:

MAC=00:`head -c5 /dev/urandom|hexdump -e '"%x"'| sed -r 's/(..)/\1:/g; s/:$//;'`

I'm using urandom rather than random because random can block, especially without mouse or keyboard movements. I don't know how random md5sum is (probably more than enough for this application), but the second example doesn't use it. Apparently bash also has a $RANDOM variable, but it is in decimal, not hex.