Tuesday, March 14, 2006

Quest for laziness 1: an end without means

The network authentication servers serve up a series of webpages which:
  1. recieve a user's username and password
  2. authenticate the user
  3. check for acceptance of usage agreement
  4. allow access
There must be a way to automate the series of HTTP requests which convey a user through this process, but first, we need to trace exactly what those requests are. To do so, we'll use the unix tool curl, with which we can practically craft HTTP requests by hand to send to the authentication servers, and then see everything they send back. We'll essentially be reverse-engineering the flow of a user's credentials through the authentication websites. Later, we can apply the fruits of these labors (hopefully) to the design of an automated greasemonkey script.

The first page a user typically encounters when reconnecting to the Davidson College campus network after an absence of some time is one that looks like the following, with a base url similar to https://cha0-na-a.davidson.edu/auth/perfigo_weblogin.jsp. The cha0-na-a subnet is different around the campus - bakn-na-a seems to work in the student union, and cha0-na-a in chambers, and there are probably others.

Authentication involves several .jsp pages, all of which share a root similar to https://bakn-na-a.davidson.edu/auth/, depending on the particular subdomain. This root will henceforth be omitted for the sake of brevity. Anyway, supplying the initial page with a successful username and password will bring the user to /perfigo_validate.jsp, which displays an usage agreement and accept / decline buttons (the terms and buttons are actually in two separate frames, each generated by a different .jsp page). The accept button loads a url similar to
where the is the user's current IP address and the 16 Xs are an all-uppercase alphanumeric string. /perfigo_cm_agree.jsp creates a page of two inline frames. The top frame presents a usage agreement, and the bottom accept and decline buttons. Pressing the accept button leads to perfigo_cm_policy.jsp which, if all went well, announces the user has successfully logged on and loads their original destination in an annoying pop-up - if I didn't mention it before, all navigation is simply redirected to the authentication pages until successful login.

Let's begin exploring by checking out the source code of /perfigo_weblogin.jsp. From it we can see 10 forms elements, 6 of which are hidden, that are used to pass information like the username and password to /perfigo_validate.jsp via a POST method. This is where curl starts to come in really handy - we can use it with the -d flag to essentially POST our own form data to /perfigo_validate.jsp. The -d expects a string representation of the form data like this: uri=&cm=&userip= etc. As soon as I figure out how to display longer code snippets in a way that doesn't overlay them across the sidebar and doesn't require manually inserting line break (which would probably break a command if it was copy and pasted into the terminal, anyway), I'll post all the curl commands I used.

A quick wrap up for now: I've been able to successfully authenticate myself solely using curl - the last command involves passing the names and values of the hidden form data of the frame with the network usage agreement accept button to perfigo_cm_policy.jsp using curl's -d option and a custom string. I think only the dynamic elements in the form are named userkey and userip - the other 5 are static (maybe they can be omitted). We can get the userkey value by posting the hidden form data (username, password, ip, intercepted IP, operating system, etc.) to perfigo_validate.jsp and looking in the src="..." url for the bottom frame (name="agree").

It's fairly simple to trace the flow and structure of information from the initial login site to the final using curl. To find out more, check out Using cURL to automate HTTP jobs. Look here for an exhaustive reference on HTTP/1.1 (rfc 2616), for a great way of getting at the guts of javascripts, definitely try the Javascript Shell, explained a bit at DiveIntoGreaseMonkey.org (we'll visit more of that site next time).

No comments: