Authenticated Remote Code Execution (RCE) Vulnerability in NextGEN Gallery
In reviewing reports of vulnerabilities to add them to our data, two of the important things we do is determining what type of vulnerability there actually is, as sometimes vulnerabilities are mislabeled, and we also check to make sure that vulnerability has actually been fixed. Those two can together when looking at a recent report of a local file inclusion (LFI) vulnerability in NextGEN Gallery.
Worth noting before we get in to the details is that the changelog entry for the version that was supposed to fix this, 2.1.57, lacked any mention of a security update.
The report didn’t really make a lot of sense. While it refers to an authenticated local file inclusion issue multiple times it also states that the vulnerability “may allow an authenticated user to read arbitrary files from the server”, which would seem to indicate that this is another type of vulnerability, an authenticated arbitrary file viewing vulnerability.
The report lacked a proof of concept for us to see how the issue would be exploited, which should have cleared up what the vulnerability actually was, but with the knowledge that issue involved a failure to”properly validate user input in the cssfile parameter of a HTTP POST request” and the changes made in the version that was supposed to have fixed this we had a better idea of what was being referred to.
On the page /wp-admin/admin.php?page=ngg_other_options there is a section labeled Styles, normally the content in the File Content section of that will be saved to the file /wp-content/ngg_styles/nggallery.css. The problem is that the value of the filename is user specified with the input “style_settings[CSSfile]”. The change made in 2.1.57 would strip out two periods in a row from that input:
513 514 | $cssfile = str_replace('..', '', $this->object->param('cssfile')); $abspath = $styles->find_selected_stylesheet_abspath($cssfile); |
That would prevent directory traversal, that is moving up a directory by using “../”. That change though did nothing to stop someone from naming the file something like “rce.php”. You could place PHP code in the File Content section and that would lead to remote code execution (RCE) when the new file with .php extension is requested. That would be more serious issue than a local file inclusion vulnerability. We haven’t been able to find a local file inclusion or arbitrary file viewing vulnerability caused by this, so maybe there was just confusion as how the vulnerability should be referred to.
Normally the ability to have done this would be restricted to Administrator level users (who would normally already have the ability to do the equivalent of this vulnerability), but the plugin allows for lower level users to gain be provided to the plugin’s capabilities. For lower level users to have access to this they would need to have been given the ability to “Change options” and “Change style”.
Within an hour of us contacting the developer about the issue they responded and starting working on better fix.
The next week version 2.1.59 was released, that attempted to fix this but ran into a common issue. Code was added to try to restrict the extension of the file to css:
487 488 489 | if (strpos($settings['CSSfile'], '.css', -0) == FALSE) { return FALSE; } |
That checks to make sure the filenames contains “.css”, so the filename “rce.php” wouldn’t be acceptable. The problem is that “rce.css.php” would be acceptable and since it ends with “.php” it would treated by the server as a PHP file.
After we notified the developers of that issue version 2.1.60 was released, which uses PHP’s functionality for getting a file’s extension and avoids the previous solution’s bypass problem:
487 488 489 490 | $file_info = pathinfo($settings['CSSfile']); if (strpos($file_info['extension'], 'css') === FALSE) { $valid = FALSE; } |
Proof Of Concept
One the page http://path to WordPress]/wp-admin/admin.php?page=ngg_other_options use your web browser’s developer tools to modify the value of the input “style_settings[CSSfile]” to rce.php, place PHP code in the File Content textarea in the Styles section, and save. Requesting the URL http://path to WordPress]/wp-content/ngg_styles/rce.php will cause the PHP code to execute.
Make sure to replace “[path to WordPress]” with the location of WordPress
Timeline
- November 16, 2016 – Original report released.
- November 16, 2016 – Developer notified.
- November 16, 2016 – Developer responds.
- November 23, 2016 – Version 2.1.60 released, which fixes vulnerability.