Thursday, December 8, 2016

Infinite Login to a Lightspeed-controllled network

If you've never heard of them before, Lightspeed Systems is a company that makes content-filtering appliances for schools and businesses. I happen to frequent a WiFi network that is heavily filtered by one of these devices, and as you can imagine, it is quite bothersome to come across a "this site is blocked" page in the course of doing my work. I understand the necessity of blocking certain pages, but not all blocking rules make sense:


The other big problem that I have on a regular basis with the system is that I have to log in to the internet every day in order to access anything. This becomes a huge problem with a headless device such as a Raspberry Pi. On my laptop, with a GUI web browser and a saved password for the login, it's not a huge issue, but with a Pi-based project that needs to connect to the internet continuously, it becomes a problem.

Last year, with an older version of the content filter, I was able to build a very simple automatic login script with Python and Requests that simply submitted the login form with my credentials and worked very well. This year, the website for the login was changed to dynamically load the login form with a highly-obfuscated and very large Javascript file. While attempting to write a new script that automated the new login system, I came across many of the different pieces of the login page.

The login page loads three Javascript files before it can dynamically render the page. Interestingly, it also loads a font from fonts.gstatic.com, which must be whitelisted to allow access through the filter even before a user is authenticated. Of my interest, however, are the Javascript files. The first one, access-default-<long hex string>.js, which is over 2.4MB, contains all the internationalization data, as well as the functions that load the page dynamically. This file is minified and obfuscated to make it very difficult to read, and its size causes some pretty bad lag in several text editors that I tried.

The second file is called data.js, which holds a base64-encoded json array that contains info about the images and Google authentication data, neither of which would help me log in. The third file, redir.js, was the one that caught my interest, containing this:

$(function(){renderAccessPage('another long base64 string')});

The function renderaccesspage() was somewhere inside the obfuscated js file, and the base64 string was another encoded json array, with more useful data inside it:

{"id":"d661beba-bc95-11e6-85be-00e0ed5686c8","ip":"10.23.25.159","host_id":"00000000-0000-0000-0000-000000000000","ident_id":14742636577554739,"filter_id":null,"tier_id":1,"reason":32769,"url":"portswigger.net/burp/","target":"portswigger.net","policy_id":null,"policy_rule_set_id":6,"cat_id":28,"cat_name":"security.proxy","is_auth":true,"can_auth":true,"auth_expire":600,"user":"redacted","host":"","host_dn":"","host_ou":"","can_override":false,"auth_override":false,"override_list_id":null,"override_time":0,"custom_access_page_id":null}

Clearly, the renderaccesspage() function takes these data and integrates them with a hidden field called redir in the form that is submitted. All my attempts to submit without this field resulted in an error, but without deciphering the Javascript, I had no idea how to generate the right data.

However, you may have already noticed that there is a field called auth_expire that is set to 600. If I'm correct, this is the login lease in minutes, as in my experience, the lease is almost exactly ten hours. Because this value is used by the function to generate the redir info, I thought it may play a part in the server deciding how long to grant a lease. Using Burpsuite and Python to edit redir.js, I was able to change the time of my lease to 60000 minutes, ensuring that I won't have to login again for a very long time.

It has so far worked, as I haven't been prompted for a login page after several days...

In conclusion, I find it strange that certain parts of the login process are left vulnerable like this. If the developers wanted the lease to be set to ten hours for everyone, it would probably be easier to do on the server rather than allow editable data like this to pass through a client device. I don't think that it's a huge vulnerability, but it may allow users access to the internet well after their account has expired, as long as the login persists in the system.

On another note, I believe this opens up an avenue for me to make my Raspberry Pi project work. Because the authentication is linked to a MAC address, I simply need to spoof my MAC address to that of the Pi, login with an arbitrarily long lease period, and then change back. Then I won't have to worry about it any more...