Working in primarily ASP.NET for the last 13 years, I didn't think much about Cross Site Scripting. The AntiXSS tools in ASP.NET are best of breed. Even without any input encoding, it's really, really tough to get XSS vectors into an ASP.NET site - especially Web Forms.
ASP.NET isn't the only platform out there, as it turns out. In fact, so far as the open web goes, it isn't even close to the most popular. Ruby on Rails, PHP, and JSP still show up everywhere, and they are not, by default, protected from XSS. What's more, mmisconfigured ASP.NET sites are more, not less, common.
With the power of today's browsers, XSS is more of a threat than ever. It used to be virtual spray paint; a method for defacing a site. Not it can be used to steal credentials, alter the functionality of a site, or even take over parts of the client computer. It's a big deal.
You can make it all go away by simply encoding your inputs and outputs. There are some simple rules to help make this happen.
First, never put untrusted data in a script, inside an HTML comment, in an attribute name, in a tag name or in styles. There is no effective way to protect those parts of a page,, so don't even start.
OK, now that we have that covered, sometimes you DO need to put untrusted data in an HTML document. If you are putting data into an HTML element, such as inside a div, use the HTML encoding that is built into your platform. In ASP.NET it is Server.HtmlEncode. Just do it. Build it into your web controls, whatever. Assume that the data coming in and going out is bad, and encode it.
That's for HTML content. How about the attributes? Width or color or whatnot? Attribute encoding. There is a good reference implementation in ESAPI.
In general, the idea is this: different parts of HTML pages require a different encoding style. The canonical reference for this is the OWASP XSS Prevention Cheat Sheet. When you are looking at your user control library for that next project, or a current one, or an old one, whatever: take a look. Does it encode inputs? Does it encode them correctly?
On a recent vulnerability assessment, I discovered an unsecured file upload and was challenged by the client.
"Was the file uploaded to the webroot, where it was executable?"
"Well, no." I said. "I don't know where it was uploaded to, but there weren't the necessary protections in place, I can assure you that."
"What can happen if it isn't executable by a web user, then?"
Oh, let me count the ways.
What we are talking about
Allowing file upload from a web page is a common activity. Everything form web email clients to interoffice management systems allow for file upload. Profile pictures are uploaded form client machines. Data is upload to support websites. Anytime you click a Browse button and look at your local hard drive from a web browser, you are uploading a file.
Keep in mind, file upload by itself isn’t a security risk. The web developer is taking advantage of built-in browser functionality, and the site itself doesn’t have any insight into your PC’s internals. File upload is governed by RFC 1867 and has been around for a long time. The communication is one way.
The code for a file upload just has to invoke an enctype of multipart/form-data, and that gives us an input type of ‘file’ as seen in this example snippet:
Please select a file:<br>
<input type="file" name="datafile" size="40">
<input type="submit" value="Send">
If the upload isn’t intrinsically bad, then what is? Well, what you upload can be bad – aiming to exploit something later, when the file is accessed.
The classic case – upload to the web root
The case that my clients were interested in is the classic problem. Back in the day, we used to let users upload files into the web directory. So, for instance, you might be able to save an image directly to the /img/ directory of the web server.
How is that a problem? If I upload a backdoor shell, I can call it with http://yourserver/image/mywebshell.php and you are pwned. Anytime I can write and execute my own code on your server, it is a bad thing. I think we can all agree on that. As a community of people that didn’t want our servers hacked, we stopped allowing upload of files to the web root, and the problem (largely) went away.
But the problem of unrestricted file upload didn’t go away. There are still a number of things that pentesters and bad guys both can do to get your server under their control. Here we’ll look at a handful of them.
Uploading something evil for a user to find later
The first, most common and probably most dangerous act is most likely the uploading of malware. Often, business and social sites both allow for uploading of files for other user’s use. If there is insufficient protection on the file upload, an attacker just uploads evilmalware.docx.exe and waits until the target opens the file. When the file is downloaded, the .exe extension isn’t visible to the user (if on Windows) and bang, we got them.
This attack isn’t much different from phishing by sending email messages. Since the site is trusted by the user, however, the malware executable might have a little more change of getting executed.
Mitigation is fairly straightforward. First, in a Windows environment, check extensions. If you are expecting a docx file, rename the file with the extension. Whitelist the extensions you expect. Second, run a pattern analyzing virus scanner on your server. There are a number of products that are designed to be run on web servers for just this case.
Taking advantage of parsers
A far more subtle attack is to directly affect the server by attacking file handlers on the host machine itself. Adobe PDF, Word and images are all common targets of these kinds of attacks.
What happens, is some flaw in the underlying system – say a PDF parser that reads a PDH form and uses the information to correctly forward the document – is exploited by a malware author. Then documents can be created that exploit this flaw and uploaded somewhere where the attacker knows they will be opened.
Let’s talk about just one of these, as an example. MS13-096 is a Microsoft security advisory that warns us that TIFF images could cause a buffer overflow in Windows. This overflow, then, could be used to execute arbitrary code on the user’s context. Remember what we said before: anytime I can write an execute my code on your machine, bad things will happen.
All of that said, doesn’t’ take a lot of technical expertise to write an exploit for that? I mean, you would need to make an image that exploited the flaw, safely put it into a Word document, then write more code to be injected into the overflow, and then have something that takes advantage of whatever we ran.
Well, the answer to that is yes, it is hard to write. So enter Metasploit. This penetration testing tool has a framework for the enablement, encoding, delivery and combination of exploits. Specifically, this one vulnerability can be baked in with already existing tools to deliver, run and get a remote shell using this exploit.
In fact, one already has.
Stealing hashes with UNC pathed templates
Not everything that Metasploit does revolves around a flaw in a software system. Sometimes you can use Metasploit to take advantage of the way software is SUPPOSED to work. For example, did you know it was possible to build a word document that uses a template that is on a UNC path? Neither did I!
Of course, in order to use that feature, Word will have to send it’s NTLM session hashes to the share. That’s only a problem if we have a listener collecting them on the other end of the wire. That’s exactly what Metasploit will do for us.
For this particular example, I use the word_unc_injector Metasploit module. This module allows me to create a Word document that calls to a template at an address of my choosing; I usually use an AWS instance for the target. This example is done in my local lab.
Once the document is made, I try and upload it into the site, as shown in Figure 1. Since it is expecting a Word document, and it got a Word document, we are in good shape.
Now we wait. When the user opens the file, Word will call out to the template as seen in Figure 2.
If it doesn’t find it, it just gives up after a while. Meanwhile, though, the NTFS session hashes are bring stores by my ‘template’ server, like Figure 3.
So what do we do about this and other document parser problems? Honestly, there isn’t much you can do. General security principles are best here:
- Whitelist so you only are allowing the document types you want uploaded.
- Don’t process files on the server.
- Run virus scanners on all workstations, and the web server.
DoS with massive files
Sometimes installing or stealing things isn’t the best path at all. Sometimes, I just want to make your server freak out and crash, so I can see the error messages. I keep a Digital Download of Disney’s Brave on my testing box just for that purpose – 3.4 gigabyte file to upload a few times, just to see how your box handles it. Usually it isn’t good.
Only the beginning
These core categories of attacks are the most common, but they are 1) not everything and 2) much broader than presented here. There are several dozen parser exploits in Metasploit, and those are just the ones that are deemed worth the effort. It is much safer to just follow slightly more-strict-than-usual security policy when it comes to file upload and save yourself the trouble later.