Arbitrary File Upload From A Different Angle


Today we will discuss about arbitrary file uploads, a less common vulnerability, but one of the most powerful

Why? Because any platform with sain developers will validate the content type and the file extension of any file they interact with.
But today I want to introduce you with a new validation attitude that I now advise everyone to use – validate the content itself.
If you are expecting an image to be uploaded – expect the content to be suited as a content of an image. If you are expecting an html file – sanitize it and make sure no script tags exist. There are plenty of libraries and tools to do that.

With that being said, a lot of companies and developers I have came across with said to me: “Why should we make all that effort when we can just host the uploaded files on a CDN (Content Delivery Network)?”.
Well, today’s story is just about that.

Freelancer.com was my first interaction with this new attack vector. They allow images to be uploaded as profile and cover pictures, DOC and DOCX files to be uploaded as resumes and far more.

But they also have a nice feature where users can write articles and publish them for others to read.
This form supports images uploads, and those images, as you can imagine, are being uploaded to a CDN (https://cdn.f-cdn.com/).
f-cdn.com is of course the official CDN of Freelancer INC.

The developers here probably assumed that since images are being uploaded to a CDN, no sanitation and content validation should be done – The form does not support HTML – so XSS cannot be done, and the CDN does not allows php files (or any other like it) to be accessed – just download them.

Well, this attitude allowed me to be able to upload a .exe file to the official CDN of Freelancer INC.

Can you imagine a scenario where a hacker will host malicious viruses on the CDN of an official company? I hope you do.
Far more, there is not size limit – any size of a file can be hosted on the CDN (although it may take time to upload it and the connection may be refused eventually).

So remember – using CDNs is not always the best option. Yes, XSSes will not affect users (because of a different domains) and yes, shells and RCEs will not endanger your server directly. But mis-validating the type of files that your CDN hosts might cause your company to a great lost.
Keep that in mind.

Ancient Purifying

Prologue

One of the first XSSes I have found was the easiest one you can imagine. There are millions, yes – millions, of websites that sanitize users input, but sanitize it wrong.

Why? because they’re agnostics. And because they don’t update their sanitizing algorithm according to the latest black/white hat community discoveries.

Purifying Basics

Basically, user input should never be outputted as HTML code. The server, by rule, should not accept HTML tags, but when you decide to accept them, you need to sanitize properly. Why? Because a small mistake in the regex you are writing will lead users to plant stored or reflective XSSes that will jeopardize your users. And you.

An example of this statement will be an ongoing report of mine.
Tagged.com / Hi5.com is vulnerable to a very simple stored-XSS attack, using a very simple payload, which of course I will not disclose until they’ll fix the issue (the vulnerability submission is waiting for their response since 2015 (!)).
The rule with sophisticated platforms is to kiss (keep it super simple). Known XSSes will probably won’t work, since a trained security team monitors these systems all the time, and the sanitizing algorithm is being updated frequently.

3rd-party Purifiers aren’t always the answer

As you already know, I don’t believe that your security should be protected by 3rd party software. If you are enough of a “big boy” to store sensitive user data (of any kind), you should also be responsible enough to keep this data safe.
Use your’e own sanitizing mechanism, based on the simple ‘do not accept HTML/SCRIPT tags’ rule, and on the recent community discoveries.

Test your mechanism, open-source it

Perfection not always has it price (Sorry Stella). A perfect input purifier mechanism will become such one only with the help of the community. Therefore, allow pentesters to challenge your mechanism, when you think its vital enough. @soaj1664ashar did such thing with his version of input purifier. You are strongly advised to look at his post about it (Google it).

Conclusion

To finish up, I’ll leave you with this outstanding quote which basically concludes everything we discussed about:

“Security is not a product, but a process” -Bruce Schneier.

Happy new year!

When Previewing Becomes Dangerous

Prologue

Previewing is cool. A lot of web sites and services offer a ‘preview before posting’ or ‘preview before buying’ option.
But sometimes previewing becomes a dirty business. Like in this case-study your’e about to hear.

Feature Streching

Blinksale.com offers an ‘Invoice Preview’ feature before you send an invoice request to another user on their web (or via email). You enters an invoice message on a simple, small textbox. HTML and Javascript codes are being forbidden and escaped when the message is sent.
Before sending the invoice, your are allowed to preview the message you are about to send to the client. Clicking on the preview button opens a pop up window which shows an example of the invoice.

When I clicked on ‘preview’ I noticed that the ‘Enter’ char I inserted was translated to a ‘<br />’ text on the GET message body parameter (in the URL). I changing the input to </script><svg onload=alert(document.domain)></svg> didn’t work. That was the stage where I’ve started to think.

Fun Part

I have decided to analyze each GET parameter in the request, and noticed that one of them was referring to a template id.
The template id was wrapping the message with a nice css and some images. It changes the background color, the foreground color and the font of the input. Then I figured: “Hmm, the template determines the input’s font. Maybe it also reads the input and has an XSS filter on the it?.

I wondered: What if the template id will be of a non-existent template? I changed the id to some random number, entered the XSS payload again and bamIt worked.

Untitled

 

The XSS filter was set per-template, which means that it worked only when an existing template id was supplied. When I supplied a non-existent template id – there was no XSS filter, no nice css or images, but still the payload was generated, which resulted with a nice reflected XSS.

Conclusion


Allowing only some of the parameters of a request to affect the output might be risky. Always be aware of the impact and the importance of any parameter you use, even the smallest one.

Blinksale patched this issue and personally thanked me via email.