On a recent engagement I encountered a drupal site which allowed for some interesting file uploads. The first file upload form had a whitelist of allowed extensions which I was not able to bypass. The second accepted archive formats including tar, zip, and bz2. It would extract the archive and place in the contents into the /files
directory of the drupal site.
The file extension whitelist was not applied to extracted files and it was also possible to include subfolders which structure would be maintained. This meant I was able to include .php
files and put them in their own subdirectory. There was a problem though, which is that in drupal the /files
directory contains a .htaccess file with the following contents:
# Turn off all options we don't need.
Options None
Options +FollowSymLinks
# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
# Override the handler again if we're run later in the evaluation list.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
This post explains that SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
sets a non-existant execution handler so that php code inside this folder will not run. Additionally it sets php_flag engine off
which should also prevent php code execution.
To get around this and get my php code to run I included a .htaccess file in the zip archive which did successfully get extracted, but for some reason a lot of the things I tried in order to enable php did not work. I wanted to share the working .htaccess for my future self and everyone else as a reference for what to do when in this kind of situation. The answer came from here:
php_flag engine 1
<FilesMatch "\.(php5?|html|phtml|php)$">
SetHandler application/x-httpd-php
</FilesMatch>