Mirko Mukaetov
Mirko Mukaetov

Reputation: 7

Prevent Arbitrary file download in Drupal 7

Drupal vurnebilyty:

It is possible to download any file that is readable by the webserver. The problem lies in the fact that the file download functionality offered by the web application does not correctly verify the parameter sent by the user that specifies which file is to be downloaded. One of the most common uses of such an exploit is to recover the source code of the application as well as configuration files which may contain passwords for other services.

Exploitation example:

The application form created in drupal allows users to upload documents.

If the form is incomplete when submitted, the user is redirected back to the form to complete the missing details. If a document was already uploaded, this form will contain the full path to the uploaded CV in a hidden HTML input field called zivotopis. After the form is correctly filled in and submitted, the server executes the following code:

<?php
if($_POST['zivotopis']) {
   // Create managed File object and associate with Image field.
   $oldFilepath = base64_decode($_POST['zivotopis']);
   if(strpos($oldFilepath,'.doc')) $extension = '.doc';
   else if(strpos($oldFilepath,'.docx')) $extension = '.docx';
   else if(strpos($oldFilepath,'.pdf')) $extension = '.pdf';
   $newFilename = strtoupper($_POST['field_item_last_name_label']).'_'.
$_POST['field_item_first_name_label'].'_CV'.$extension;
   $newFilename = str_replace(" ", "-", $newFilename);
   $newFilepath = drupal_realpath(dirname(__FILE__))."/tmp/".$newFilename;
   copy($oldFilepath, $newFilepath);
// ...

As can be seen, the provided base64-encoded path in zivotopis will be used as $oldFilePath in the call to copy(). A malicious user can, therefore, provide any arbitrary file path and that file will be copied to the webroot under a new name.

When I submit the form but intercept the HTTP request. Adding new POST parameter called zivotopis to the request with ./sites/default/settings.php in base64 encoded format, it should look similar to this:

...
-----------------------------7667788801930707109771964994
Content-Disposition: form-data; name="zivotopis"
Li9zaXRlcy9kZWZhdWx0L3NldHRpbmdzLnBocA==
-----------------------------7667788801930707109771964994
....

After visiting uploaded file url it contains the database credentials!

My question is

How can I prevent to not accept user-controlled file paths?

or why not disable PHP eval() function?

Any ideas on how to follow Drupal Security Glydeness

Upvotes: 0

Views: 188

Answers (1)

MilanG
MilanG

Reputation: 7114

Drupal provides public and private file systems. For each file field (in webform or content type settings) you can select which one should be used. Also, under Media -> File system you can specify path to both of those 2 systems.

I didn't use private system, but I guess that Drupal will place .htaccess file inside private files root dir, preventing direct access to files located there and serve files over PHP, with checking access rights of current users.

Again, I'm not 100% sure, but should be possible to set private dir totally out (above) of site web root dir (inaccessible by web server), so even .htaccess protection won't be needed.

Upvotes: 2

Related Questions