Livesshattack.net Blog
Attack now
ssh root@livesshattack.net
Attacks to date
counting...

2016-02-28 03:09:00

Author: Willie Stevenson

xss application security

Like everybody else, I wanted to generate traffic to my new site. So I posted to hackernews, opened up htop on my, at the time, 512MB Digital Ocean droplet, and kept a close eye on my live visitor feed from google analytics. I wasn't expecting much, especially at 11pm at night.

The visitors started to trickle in.

A few minutes after posting to hacker news.

After about 10 minutes, I surpassed 100 active views.

10 minuets later.

Within the next 5 minutes I passed 250 active viewers and watched as my cpu and ram hit 50%+ load a few times.

I started to laugh at myself at this point.

I started to contemplate whether or not I should upgrade my digital ocean instance to a beefier one, however, my worries focused on a whole different issue when I saw this:

This is what xss looks like. Because I had forgotten to sanitize all output going to the div that contained the live tail, I became vulnerable to xss.

This was the problematic block in AjaxLongPoller.js

$.each( loglines, function( key, val ) 
{
	l = l+1;
	//console.log("Val "+val.toString());
	items.push("\n"+val.toString());
});// end each

var newlines = items.join( "" );
$("#tail-here").prepend(newlines);

So loglines, incoming lines from my auth file, are passed to the foreach statement. We go over each element and push them to the items array. We then take the items array and join each element together with no spaces (because each element has a line break appended to it). The result, usually one line, is then prepended to the div element where we are displaying our tail of the log.

The one thing that is missing here is sanitization. We can add it with the following block:

$.each(loglines, function(key, val) {
	l = l + 1;
	$("#tail-here").prepend("\n");
	items.push(val.toString());
	var newlines = items.join("");
	$("#tail-here").prepend(document.createTextNode(newlines));
	items = [];
}); // end each

I decided to use createTextNode(), which renders all incoming lines from our log file as text instead of html before we append them to the div container. Notice that this implementation is also a way to ensure each individual line coming from the log file gets sanitized rather than all lines that were, in the previous example, stored in the variable newlines. If we were to sanitize all lines at once, we wouldn't be easily able to put each line from our log file on a new line in our div container.

Immediately after the community and I discovered the vulnerability, I took the site down and issued the fix.

I was pwned by hn, but, for that reason, I have learned to be even more careful.