Hacker News new | comments | ask | show | jobs | submit login
Zero-day in jQuery plugin sample code exploited for at least three years (zdnet.com)
216 points by john37386 86 days ago | hide | past | web | favorite | 68 comments

Larry Cashdollar here. I don’t blame the author either. None of the folks including my self knew .htaccess support was no longer default.

Author of jQuery File Upload here.

The vulnerability is a combination of Apache v.2.3.9's default setting to not read .htaccess files and my mistake of relying on .htaccess to enforce security of the sample PHP upload component.

To give you some context on how this could happen:

- As the project name implies, this started as a client-side jQuery plugin, with a dummy PHP script to echo out the uploaded file

- Over time, I added a couple of sample server-side upload components, including two for Google App Engine (Python + Golang) - which I used for the demo - and one for PHP, which I never used myself in production

- I used the PHP component for local tests with various possible file uploads, including very large files and chunked uploads, which required enabling all file types for upload. My thinking was that allowing all file types for upload is not critical as long as the handling of those files is properly configured.

- Prior to adding the .htaccess file, I mistakenly assumed developers would configure their Apache server themselves so that no PHP scripts would be executed in the uploads folder. It was only added in this commit: https://github.com/blueimp/jQuery-File-Upload/commit/13931c7...

- The Apache servers I tested with always had support for .htaccess enabled, so I never bothered to check that the default Apache configuration since version 2.3.9 actually disabled it

- The original .htaccess configuration didn't even prevent script execution in all Apache configurations and had to be fixed, see: https://github.com/blueimp/jQuery-File-Upload/pull/3381

Looking back, there are a couple of things that I should have done differently:

- Move out the server-side components into separate repositories

- Inform users better about file upload security - see https://github.com/blueimp/jQuery-File-Upload/wiki/Security

- Never assume people actually read information about security

- Never rely on .htaccess for security configurations in Apache

- Make sure that published code is secure in all default configurations

- Never allow all file types for upload by default, even if it is secure in your configuration

- Recommend users to not upload files in the same root as their executable web application

- Always follow security best practices, even if it makes setup for users more difficult

I wanted to make it really simple for users to install a generic and secure file upload service with a great user interface. Unfortunately, security best practices and ease-of-use are often at odds to each other.

Bonus info:

The client-side component had a cross-site scripting vulnerability in the Iframe Transport HTML site back in 2012: https://github.com/blueimp/jQuery-File-Upload/commit/4175032...

The App Engine components had an open redirect vulnerability back in 2015: https://github.com/blueimp/jQuery-File-Upload/commit/f74d2a8...

I really don't blame the author here, sure there was an issue with the sample code - but come on it was sample code. If someone is implementing user uploads they should really do the due diligence and understand what the sample code does.

To be honest I'm not really that surprised that the vulnerability stayed hidden for so long; many PHP users are hobbyists or come from a more traditional "webmaster" background. This is not to say that there aren't good PHP programmers, just that there is a large group of novices.

Not a good way to look at it. Sample code is equivalent to production code. It will be copied, verbatim, if it appears to work. Once it has the appearance of working, it isn’t looked at again. It doesn’t matter if you think people should be doing this or not. The only thing that matters is they will.

Exactly this.

For most developers there doesn't seem to be a differentiation between example code on a blog post and actual producation code.

It wasn't exactly hidden seeing as how there was a YouTube video titled 'Exploit jQuery File Upload Vulnerability' available since 2015. I don't blame the author (given the timing of the Apache change it probably would have been easy for him to overlook[1]) and it is surprising that this took years for anyone to make him aware of the issue since the exploit wasn't exactly unknown. Apparently there's some groundbreaking work left to be done in infosec searching on combinations of various library / application names and 'exploit'...

[1] I assume that like most of the rest of us he was lagging behind the latest and greatest Apache release a bit. So when he was writing/testing this, it probably wouldn't have been an issue.

Unfortunately, I never tested it with an Apache configuration that had .htaccess support disabled and so it simply did not occur to me that the default was "off".

I think the bigger issue was that the PHP sample code allowed all file types by default - this would not only affect Apache, but any Webserver that had broad rules to execute PHP scripts found in a directory.

Originally I didn't see this as an issue as I trusted developers to securely configure their server to make sure no uploaded files would be executed, which is why the .htaccess security settings were only added later in this commit: https://github.com/blueimp/jQuery-File-Upload/commit/13931c7...

But neither was the documentation informing developers clearly enough about the security implications, nor should I have relied on people actually reading security notices.

Fair enough... but I still don't blame you ;-)

Hehe, thanks! :)

I'm not going to throw stones either. But I would encourage developers to make their sample code robust. Especially as

> many PHP users are hobbyists or come from a more traditional "webmaster" background

I seem to remember a somewhat related problem with WordPress. The issue there was made worse by the fact the sample code was part of the default install and so available to anyone who knew the URL.

Edit: A quick search shows I was thinking of an XSS attack. It was due to some bad example code in the default theme folder, which is by default publicly accessible even if not used.


I agree, the sample code should have been secure by default (with all web server configurations) because it's guaranteed that someone will use it as is without checking their own server configuration.

And inexperienced webmasters were definitely part of the target group, since I wanted to make is as accessible as possible, including for those users on shared hosting webspace without access to the Apache configuration files.

The simplicity of the sample code is a strong factor in deciding what library to use for a task.

If the 'hello world' example is hundreds of lines, then I imagine the effort of using this library to be a few days at least.

If the 'hello world' example is just 3 lines, then I can probably integrate this library into my service in 10 minutes.

Making the sample code more robust (handling errors, checking for legacy configs, etc.), makes it longer, which in turn puts off people like me.

Thanks for your comment.

I do think that I share at least part of the blame. Enabling all file types by default was not necessary and would have prevented this issue.

Especially since there are so many inexperienced developers using PHP, the defaults should have been secure in every perceivable Webserver configuration.

Understanding what the code does is not how people generally write software. They slap components together, copy&paste examples and randomly move code lines around until it seems to work good enough. So your examples better be correct :)

> The Apache servers I tested with always had support for .htaccess enabled

For what it's worth, you'll find lots of people disable support for .htaccess for performance reasons.

It's probably less of an issue these days, but if you support .htaccess files, apache reads the .htaccess file for the current directory, and those for every parent directory, and it happens on every single access.

So for example someone accessing http://foo.bar.com/thing/goes/here would cause the webserver to check for and read /thing/goes/.htaccess, /thing/.htaccess and /.htaccess. If you imagine you've done the sensible thing and got your content nicely split out, you can probably see how that can hurt performance. *nix OSs will be smart and cache the content etc. but you're still wasting time on every access making sys calls.

If you put the access rules in the apache config file, everything is set-up at initialisation time and it never has to make further checks.

Agreed - in addition to performance issues, there are also security issues if .htaccess support is enabled - because they can override security settings.

Originally the PHP example code didn't have a .htaccess file - I trusted developers that they would configure file uploads securely by themselves, e.g. via Apache configuration files.

The reason I added it was to support developers on shared hosting plans without access to the Apache configuration - something which was very common back then.

Don't beat yourself up. Your response shown here is insightful and reasonable. Well done!

Thanks a lot!

"Zero-day in popular jQuery plugin" is a bit misleading for the title then. More like "Zero-day in copy pasted code in PHP if apache incorrectly configured".

I think the title is substantially misleading in that it suggests the bug is in the plugin itself. Maybe "Zero-day in PHP server sample code provided with popular jQuery plugin"?

That’s not really true, given that the default Apache confit is vulnerable.

That's exactly what a security post-mortem should look like.

- What went wrong

- Why did it go wrong

- What can be done to ensure this doesn't happen again

Everyone makes mistakes once in a while, the key is learning from them.

Well done!

Thanks a lot!

By now I've also updated the project page with

- Security-related releases on top of the main page: https://github.com/blueimp/jQuery-File-Upload#%EF%B8%8F-secu...

- Security guidelines linked in various places on how to securely set up file uploads: https://github.com/blueimp/jQuery-File-Upload/blob/master/SE...

- A list of the fixed vulnerabilities with instructions on how to fix it for the recent critical one: https://github.com/blueimp/jQuery-File-Upload/blob/master/VU...

> Never allow all file types for upload by default, even if it is secure in your configuration

The general form - never use default-allow - should be used in most situations where set of possible inputs cannot be exhaustively enumerated. In most situations, you cannot enumerate badness[1]. Instead of trying to define valid input by specifying it's inverse, it's far simpler (and safer) to use default-deny and specify valid input directly.

[1] http://www.ranum.com/security/computer_security/editorials/d...

Also known as "use a whitelist instead of a blacklist".

Although I agree with you in a general sense, in this case there was no blacklist mistakenly used.

If the server is configured to serve uploaded files securely, it is feasible to allow all file types for upload (e.g. think of Amazon S3 or Google Cloud Storage).

However since there is no way to ensure that the server security settings to securely handle uploaded files are applied, limiting file uploads with a whitelist minimizes the attack vector sufficiently.

Since this is about vulnerabilities in a third-party dependency (ImageMagick/Ghostscript), the recommendation in the blog post to use the GD library instead (what the image_library 0 setting does) is not very sound, as libgd also had a number of vulnerabilities in the past, albeit less than ImageMagick: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Libgd

A better recommendation is to securely configure ImageMagick, or even better: to use a safer image processing library (e.g libvips or imageflow).

I’ve added some mitigating code and recommendations on how to securely configure ImageMagick to jQuery File Upload, please have a look here: https://github.com/blueimp/jQuery-File-Upload/blob/master/VU... https://github.com/blueimp/jQuery-File-Upload/blob/master/SE...

Thank you for coming that clear.

Thanks for your comment.

I think in situations like this it's important to take responsibility and provide as much transparency as possible.

Relying on apache version specific defaults is always the wrong approach.

But everything else can be avoided with a whitelist of acceptable types by default.

are other web servers vulnerable ? for example, wildfly jboss server,??

If the upload directory is securely configured, no.

Please refer to the vulnerability documentation here to see if you are affected: https://github.com/blueimp/jQuery-File-Upload/blob/master/VU...

There is no blame on you. There is no way you can provide a configuration that will be secure on every server.

My recommendation: add a big warning message that there is at least one known security hole and many unknown ones in the server code and it is up to the just to secure their server properly.

Then fix the demo code but leave the warning there.

It's always up to the developers to check the system they build for security problems. They could use the best frameworks in the world and copy thoro reviewed example code. The end result might still have huge security problems.


I already got a helpful pull request for the main README.me that I've updated by now with

- Security-related releases on top of the main page: https://github.com/blueimp/jQuery-File-Upload#%EF%B8%8F-secu...

- Security guidelines linked in various places on how to securely set up file uploads: https://github.com/blueimp/jQuery-File-Upload/blob/master/SE...

- A list of the fixed vulnerabilities with instructions on how to fix it for the recent critical one: https://github.com/blueimp/jQuery-File-Upload/blob/master/VU...

The demo code was fixed as soon as I could confirm the report from Larry Cashdollar.

OK. I'll be that guy. Is there nobody who is going to talk about Larry Cashdollar, the person who discovered this vulnerability and first reported it?

I'm honestly not sure how I'd be more impressed; if you told me this man actually uses this as his real name in his daily life, or by finding out that this is actually his birth name.

He's a former co-worker of mine, and is an awesome dude in many ways.

His name really is Larry Cashdollar, born and raised. Sometimes I wrote his name as 'Larry $$' though.

Larry was also super helpful in identifying the underlying issue and very polite in his emails.

Would definitely write another security vulnerability into my code again if I knew that Larry would report it. ;)

Thanks, :-)

> Would definitely write another security vulnerability into my code again if I knew that Larry would report it. ;)

Yet more proof that social media will bring the Internet down!

It's almost like he had JQuery selectors deep within his DNA! He was BORN to find this bug. The prophecy is true!

It appears to be a somewhat common surname. Looking up Wikipedia, there is Cindy Cashdollar (a musician), and a few others: https://en.wikipedia.org/w/index.php?search=Cashdollar+-%22C...

Isn't a JQuery Plugin something that executes on the client-side? If so then how can something on the client-side compromise the security of a server? Isn't the fault on the server-side?

Or is this a PHP server-plugin which if installed on a PHP server makes them insecure? But of course anything you install on server can make it insecure. No?

There is an example PHP code in the same repo and people copy-pasted that into production.

The issue is not in the front-end jQuery library, despite the title.

> If so then how can something on the client-side compromise the security of a server?

This is answered in the plug-in author's thorough note, posted a couple hours before you posted this.

For a breakdown on how this could happen, please see my comment here: https://news.ycombinator.com/item?id=18267309

What other vulnerabilities did this backwards-incompatible Apache change cause? Probably many people rely on .htaccess, for example to disable access to non-public files or disable php execution on a DIY CMS file sharing area.

Sounds like the risk from this is not widely known. Probably the correct solution for Apache would have been to detect presence of now-ignored .htaccess files and signal an error.

That was my thought as well.

I think one of the reasons nobody reported this earlier was that people simply assumed that .htaccess support was the default - Larry Cashdollar, the security researcher, also confirmed this: https://news.ycombinator.com/item?id=18271880

Isn't this a click-baitish title? I would say that this is a configuration issue and not "exactly" a vulnerability and basically get off my lawn.

Reading blueimp's and larry's comments here I envy their constructivity, open mindedness and professionalism.

Thanks! Comments like yours are what keeps me motivated to continue contributing to open source software.

But although the title is somewhat click-bait, I still think this counts as a vulnerability in my project, since there is a possible combination of default Apache setting and default project files that is exploitable.

Another apache disaster, blueimp's plugin has nothing to do with it: it's common for script kiddies to try to upload php executables on php sites, and sometimes it works.

I do think that my project is responsible and not Apache, since I provided sample code that was not secure by default when used in a default Apache configuration as is.

However I wish Apache would have changed their default config in a way that would have signalled an error if an .htaccess file is present but not applied.

Something that HA user fulafel also pointed out here: https://news.ycombinator.com/item?id=18272407

Can someone share some information on the reasoning behind httpd's default handling of htaccess files? How does ignoring a security feature that many relied on improve security?

I suspect it's so that a user can't accidentally make security worse by fiddling with security settings that they don't understand. That said, I might've considered turning any page that had the disabled .htaccess settings into a 500 response instead of just keeping on like everything is working fine.

They disabled per-folder .httaccess files for performance reasons. Also for security, as it allowed server owners to control the entire server via global configs and prevent badly coded CMSs and plugins from opening security holes and bypassing stronger server-wide rules.

Haven't seen this sample code, but in general letting your users set the filename of anything on your server is a bad plan.

If the upload script just generated a random filename (046359905445.bin), and then stored the mime type, users filename, other metadata, etc. in a database, that would be a much better design.

I agree with you that this would be the safer route. For a production file upload service, file uploads should ideally stored in a specialized blob store, e.g. Amazon S3 or Google Cloud Storage.

However the PHP code was written as easy-to-use sample code and I did not want to introduce a database as dependency and keeping the sanitized filename plus extension keeps the meta information intact.

If I had provided better information about how to securely configure the Webserver to allow all file types for upload, using the original - but sanitized - filenames would not be an issue.

So this afect only apache? Anyone have any thoughts on nginx, IIS and other web servers like tomcat, websphere?

Please refer to the vulnerability documentation here to see if you are affected: https://github.com/blueimp/jQuery-File-Upload/blob/master/VU...

Does NGINX, IIS, Tomcat, etc support .htaccess? No.

I'm curious as to how this could be a widely known exploit in the hacker community, but no one reported it until 3 years after its publicity.

It's not 3 years old, we've been exploiting it when we were 14 yr old trying to find server to host warez content, and has nothing to do with the plugin itself: it's all about apache's mod_php configuration: does it allow execution of php files that are in the directory where users upload their avatar ? If yes, then they can try to upload a php script and execute it on the server.

In 2018 Apache, phone and jQuery is a doormat saying "please hack my servers"

Hey Larry $$

Please don't post unsubstantive comments here.

Don't you think maybe he's heard this a few times already?

We detached this comment from https://news.ycombinator.com/item?id=18271880 and marked it off-topic.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact