One Drop on A Spider Web
On 6th February 2007, I’ve published an article titled Playing in Large, which discusses various ways of injecting large JavaScript payloads into tiny XSS holes. The technique that I used as an example is quite simple. In general, all attackers need to do is to place their malicious payload behind the fragment identifier (# sign) and evaluate it within the attacked application context. This can be achieved by using something like this: eval(location.hash.substr(1)).
This works really well when you are restricted in terms of the vulnerable field length. It was found that we can squeeze XSS payloads into 50 to 60 characters in size. Keep in mind that this is only when we use script elements (<script/>), which is by far the longest way of doing it. In some case, we can inject a couple of MBs of JavaScript inside a vulnerable application by composing a XSS string that is around 25 to 30 characters long.
Another interesting point to outline is that the fragment identifier technique is quite stealth. Every information that is behind the hash (#) sign is not sent to the server. The fragment identifier is only used on the client. This means that this technique is suitable for circumventing firewalls, intrusion detection and intrusion prevention systems.
It is recommended to check the Playing in Large article, if you are not familiar with this technique.
In this post, I will show you a technique that I have developed in the last half an hour, which is as stealth compared to what we have discussed before, but a lot smaller in terms of length of characters needed and does not require special characters such as:
- dots .
- square brackets []
- spaces
- other meta characters that are usually used inside JavaScript
The character set that is required is composed of lower case letters and the round brackets (). In order to explain how the technique works, I am going to lay out a hypothetical scenario which is as follows:
https://acme.com/vuln.php3?"></script><script>alert(1)</script><!--
It is clear that the example above is vulnerable to XSS. However, although we can alert the character 1 on the screen, we are not able to do anything else, mainly because the site converts special characters into underscores (_). This means that the payload: "></script><script>alert(document.cookie)</script><!– is converted to "></script><script>alert(document_cookie)</script><!–, which fails mainly because document_cookie does not exists. If we try to inject more complicated JavaScript, we pretty much end with the same problem. What’s even worse, single quotes and double quotes are also sanitized.
One thing is for sure, we might be able to inject remote script files by using various browser quirks such as <script src=domain/script. However, these type of payload is unstable and require to host a file in a server in rather strange way. Remember, most meta characters are not allowed, including dots (.) and columns (:).
I was toying around this problem for a bit when I realized that the best way to bypass this restriction is to reuse something that is part of the DOM already. I needed something that fits into the following vector:
https://acme.com/vuln.php3?"></script><script>eval(something)</script><!--
… where something is a variable part of the DOM global space and can be controlled from outside. There are plenty of such kind of variables but not that many of them are suitable for the job. For example we can inject stuff into the referrer and try to evaluate that. It is possible but very complicated since we need to find a way of spoofing this information. After digging into DOM I found a global namespace variable, which seamed that could work.
name is a global namespace variable that defines the name of the current window. Most of the time, name contains nothing but a blank string. However, once we call a page within an iframe or an object with the appropriate attributes, the name value is changed to reflect that. In order to see how name looks like when opened from a browser window and an iframe try the following:
- create a blank html page with the following content:
<script>alert(name)</script> - open the page within your browser - you should see a blank alert box
- create a blank html page with the following content:
<iframe name="test" src="path_to_the_first_page.htm"></iframe> - open the page within your browser - you should see an alert box with the message test
If you haven’t realized yet, we can use this technique to circumvent filters in a very clever and quite sneaky way. Let’s get back to our hypothetical scenario with the XSS vulnerability in acme.com which cannot be exploited easily. By using the technique I discussed above, we can bypass the restriction and here it is how:
<iframe src="https://acme.com/vuln.php3?%22%3E%3C/script%3E%3Cscript%3Eeval%28name%29%3C/script%3E%3C%21--" name="/* your JavaScript payload here*/ alert('xss')"></iframe>
If you take the code displayed above and place it inside an innocent HTML page, you will be able to XSS anyone who visits it and is on the acme.com domain, although acme does a good job of sanitizing some of the meta characters.
Some of the sceptical XSSers may not see the point of using this technique for a number of reasons. The first reason is based on the fact that there are other ways to exploit acme.com. This is true, but the example here was provided as a case study only. Very often we can alert(1) but nothing else, because the string needs to be short and can only contain standard characters. This is exactly when this technique is most suitable for, because the character set is standard and eval(name) is a lot like alert(1).
Keep in mind that this attack leaves a very small footprint on the attacked system. The data that is contained in the name variable is never submitted to the server. It is worth mentioning that HTML/XML attributes are usually allowed to contain quite a lot of data which allows attackers to include entire XSS frameworks within the boundaries of name.
This technique was published in order to raise the security awareness in regards to XSS (Cross-site Scripting) attacks. There are more then one way of doing things, which we usually overlook.


comments
Very good writeup, I was doing quite a lot of research on this because such a situation was present on YouTube (http://www.youtube.com/advertise) a few days ago.
what is interesting about this technique that is a combination of reflected XSS with a little help from the DOM.
This is VERY powerful. We’re saying that if we can run
as our XSS payload, then we can run JavaScript without any restrictions whatsoever.
So when testing for XSS, if we get a blank alert box when injecting
then we know we can run absolutely anything by visiting a third-party page that embeds our magic iframe.
If yours is new, I guess I can patent the following:
Much easier to post everywhere, because it’s self-contained and you don’t need to control the window name.
Cheers
–
There’s a brower safer than Firefox… it’s Firefox, with NoScript - http://noscript.net
Giorgio, no one is patenting anything, but your trick is cooler I must admit. Nice stuff… I love it. However, mine is still smaller… :) but heck I love self-contained stuff so you win. :)
pdp, I was just kidding - Cenzic is enough about patents.
Of course I wouldn’t have figured out mine if I didn’t read your [a-z\(\)] challenge, so many thanks for inspiration ;)
–
There’s a brower safer than Firefox… it’s Firefox, with NoScript - http://noscript.net
Giorgio, I’ve totally ignored the with statement. To be honest with you, I am not using it that often. In fact, I cannot remember the last time I’ve made any use of it apart from the time when I tried to create a sandbox within JavaScript which didn’t work, so I had to use full blown iframes to imitate similar characteristics.
Anyway, great stuff. RSnake should include this one into his cheat sheet.
Giorgio,
That’s a killer snippet. Thanks a lot for that.
Use the right tool for the right job… although I find ma1 technique rather cool, it may not work in some cases. For example, changes in the fragment identifier wont result in page refresh which is what you might want to achieve in some cases. Also, there are ways to make the fragment identifier to go away via a series of redirections, which is something that happens quite often. Another bad thing about the fragment identifier technique is that although everything is inside the URL, it looks too suspicious. Very often, attackers will use a 3rd party website which upon user arrival does the actual exploitation. Not to mention the fact that in some cases the # hash is used as communication mechanism between frames which are served from different origins. Any use of the fragment identifier will break the communication. You don’t want to do that if you want to be stealth.
Here is an example. Let’s say that you have a worm that exploits the user on several domains. For sure you can use the fragment identifier technique and compose URLs which are included inside a hidden iframe. However, you need to do all the manual work for nothing, when you can simply create the iframe, assign the name or the target with your payload and rotate the src value with the URLs you want to exploit. XSSED.com has tones of vectors that simply
alert(1). All we need to do in order to make them work is/alert\((1|'XSS'|"XSS")\)/eval(name)/iand start rotating them inside an iframe. The chances of this technique to work are higher mainly because we do not add that much more characters into the payload. We don’t have to do any characters counting and we don’t have to think whether there is something before our code that makes uses of the information after the # hash. believe me, more and more applications make use of the hash today.To sum up… do not be ignorant. use the right tools for the right job. as you can see, there are real applications of the technique I described.
I’m not sure if you all know it or not, but the contents of window.name are persisted across domains for the lifetime of the browsing context. This means window.name can be used to as a global session storage system.
For example, site1.com writes a value into window.name. Any other websites that are visited in that browsing context (i.e. that browser tab or single browsing window) can read or write this value. In fact, I’ve got some cool demos where I track individual users across domains without web bugs/3rd part image server using JavaScript and window.name.
In fact, we touch on this in the upcoming Ajax security book in our attacking offline Ajax apps chapter. I even wrote a source code compatible implementation for Firefox’s sessionStorage object for ther other browsers.
Acidus,
I didn’t know that. Actually this is very funny. I cannot see to what extend
window.namecan be used for malicious purposes although it is sort of interesting since it is almost like some kind of global dashboard where everyone can leave a message. So, we can implement some sort of a system where sites leave information about the user insidewindow.nameand other sites can reuse that information in a clever way.i would like to patent (built on the maone’s one)
What about frame breaking code on acme?
Kishor, what do u mean?
i would like to patent (built on the maone’s one)
please tell me when the registration process is finished : )
http://www.ush.it/2007/06/27/x.....-payloads/
ascii, I am opening a patent bureau. Please send your submissions to contact at gnucitizen.org or contact the GNUCITIZEN group at group at gnucitizen.org. thanks.
This code inside the page which is vulnerable:
As per Acidus’s comments
Here is what I tried out,
1.html:
and
2.html:
2.html still alerts XSS!
So it means we can use window.name even if frame breaking code is present.
So another ‘with’ may be necessary for window’.’
SirDarckCat and I are having fun with PHPIDS at http://groups.google.de/group/.....c8cc934867
Incidentally, he just added some extra spice to hash (fragment) payload attacks:
This works if you break the hash with a %0A (newline) before your payload, because:
So simple, so nice :)
–
There’s a brower safer than Firefox… it’s Firefox, with NoScript - http://noscript.net
Neato!