Protect Your Uploads Folder with .htaccess


If you’re like me you may have sites that allow users to upload images. This could easily be a potential backdoor for hackers. I came up with these sets of rules that have worked for me. I will continue to update these rules as I discover other vulnerabilities and methods of attack. For those copy and  paste junkies, the code is directly below. For those more interested in what the rules actually do, continuing reading below the first box of code.

For you copy and paste junkies here is the entire code (copy and paste into notepad, save as .htaccess, and place it in your uploads folder):

[There is an updated version of this that is lighter and more secure at my self hosted website: http://thomasoliver.info/protect-your-uploads-folder-with-htaccess/ ]

# Don't list directory contents
IndexIgnore *
# Disable script execution
AddHandler cgi-script .php .php2 .php3 .php4 .php5 .php6 .php7 .php8 .pl .py .js .jsp .asp .htm .html .shtml .sh .cgi
Options -ExecCGI -Indexes

# Only allow access to this directory if they are coming from your domain; excluding you, your server, Google and any other IPs
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^(xxx\.xxx\.xxx\.xxx|xxx\.xxx\xxx\.xxx|66\.249\.)
RewriteCond %{HTTP_HOST} !^(127\.0\.0\.0|localhost) [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?yourdomain\.com/ [NC]
RewriteRule .* http://yourdomain.com/ [L]

# Secure php.ini and .htaccess
RewriteRule ^(php\.ini|\.htaccess) - [NC,F]

# Block shell uploaders, htshells, and other baddies
RewriteCond %{REQUEST_URI} ((php|my|bypass)?shell|remview.*|phpremoteview.*|sshphp.*|pcom|nstview.*|c99|c100|r57|webadmin.*|phpget.*|phpwriter.*|fileditor.*|locus7.*|storm7.*)\.(p?s?x?htm?l?|txt|aspx?|cfml?|cgi|pl|php[3-9]{0,1}|jsp?|sql|xml) [NC,OR]
RewriteCond %{REQUEST_URI} (\.exe|\.php\?act=|\.tar|_vti|afilter=|algeria\.php|chbd|chmod|cmd|command|db_query|download_file|echo|edit_file|eval|evil_root|exploit|find_text|fopen|fsbuff|fwrite|friends_links\.|ftp|gofile|grab|grep|htshell|\ -dump|logname|lynx|mail_file|md5|mkdir|mkfile|mkmode|MSOffice|muieblackcat|mysql|owssvr\.dll|passthru|popen|proc_open|processes|pwd|rmdir|root|safe0ver|search_text|selfremove|setup\.php|shell|ShellAdresi\.TXT|spicon|sql|ssh|system|telnet|trojan|typo3|uname|unzip|w00tw00t|whoami|xampp) [NC,OR]
RewriteCond %{QUERY_STRING} (\.exe|\.tar|act=|afilter=|alter|benchmark|chbd|chmod|cmd|command|cast|char|concat|convert|create|db_query|declare|delete|download_file|drop|edit_file|encode|environ|eval|exec|exploit|find_text|fsbuff|ftp|friends_links\.|globals|gofile|grab|insert|localhost|logname|loopback|mail_file|md5|meta|mkdir|mkfile|mkmode|mosconfig|muieblackcat|mysql|order|passthru|popen|proc_open|processes|pwd|request|rmdir|root|scanner|script|search_text|select|selfremove|set|shell|sql|sp_executesql|spicon|ssh|system|telnet|trojan|truncate|uname|union|unzip|whoami) [NC]
RewriteRule .* - [F]

# Disable hotlinking of images
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} \.(jpe?g?|png|gif|ico|pdf|flv|swf|gz)$ [NC]
RewriteCond %{HTTP_REFERER} !^https?://([^.]+\.)?yourdomain\. [NC]
RewriteRule \.(jpe?g?|png|gif|ico|pdf|flv|swf|gz)$ - [NC,F]

# Only the following file extensions are allowed
Order Allow,Deny
Deny from all
<FilesMatch "\.([Jj][Pp][Ee]?[Gg]?|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Gg][Zz]|[Pp][Dd][Ff])$">
Allow from all
</FilesMatch>

# Block double extensions from being uploaded or accessed, including htshells
<FilesMatch ".*\.([^.]+)\.([^.]+)$">
Order Deny,Allow
Deny from all
</FilesMatch>

# Only allow GET and POST HTTP methods
<LimitExcept GET POST>
Deny from all
</LimitExcept>
__________________________________________________________

The first part of the rules:

# Don't list directory contents
IndexIgnore *
# Disable script execution
AddHandler cgi-script .php .php2 .php3 .php4 .php5 .php6 .php7 .php8 .pl .py .js .jsp .asp .htm .html .shtml .sh .cgi
Options -ExecCGI -Indexes

 

Index Ignore *
Options -Indexes

They first disable directory viewing, listing, etc.

AddHandler cgi-script .php .php2 .php3 .php4 .php5 .php6 .php7 .php8 .pl .py .js .jsp .asp .htm .html .shtml .sh .cgi
Options -ExecCGI

The AddHandler directive sets all the files ending in those extensions to be handled as cgi-script.

The next line uses the Options directive to disable cgi-script completely.

This is special so that they fall under the jurisdiction of the -ExecCGI command, which also means -FollowSymLinks

**NOTE** In some instances you may see the rules combined as in Options -ExecCGI -Indexes. I did this to make the rules more efficient.

__________________________________________________________
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^(xxx\.xxx\.xxx\.xxx|xxx\.xxx\xxx\.xxx|66\.249\.)
RewriteCond %{HTTP_HOST} !^(127\.0\.0\.0|localhost) [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?yourdomain\.com/ [NC]
RewriteRule .* http://yourdomain.com/ [L]

These set of rules declare that if anyone but the indicated IPs or hosts try to directly access this directory, they will be sent back to the home page.

You could put your server IP, your static IP, and any others like Google if you would like to allow them access.

__________________________________________________________
RewriteRule ^(php\.ini|\.htaccess) - [NC,F]

These rules denies access to php.ini and .htaccess. In my opinion, Rewrite seems the best way to deny access to these files.

**NOTE** There is no $ intentionally.

__________________________________________________________
RewriteCond %{REQUEST_URI} ((php|my|bypass)?shell|remview.*|phpremoteview.*|sshphp.*|pcom|nstview.*|c99|c100|r57|webadmin.*|phpget.*|phpwriter.*|fileditor.*|locus7.*|storm7.*)\.(p?s?x?htm?l?|txt|aspx?|cfml?|cgi|pl|php[3-9]{0,1}|jsp?|sql|xml) [NC,OR]
RewriteCond %{REQUEST_URI} (\.exe|\.php\?act=|\.tar|_vti|afilter=|algeria\.php|chbd|chmod|cmd|command|db_query|download_file|echo|edit_file|eval|evil_root|exploit|find_text|fopen|fsbuff|fwrite|friends_links\.|ftp|gofile|grab|grep|htshell|\ -dump|logname|lynx|mail_file|md5|mkdir|mkfile|mkmode|MSOffice|muieblackcat|mysql|owssvr\.dll|passthru|popen|proc_open|processes|pwd|rmdir|root|safe0ver|search_text|selfremove|setup\.php|shell|ShellAdresi\.TXT|spicon|sql|ssh|system|telnet|trojan|typo3|uname|unzip|w00tw00t|whoami|xampp) [NC,OR]
RewriteCond %{QUERY_STRING} (\.exe|\.tar|act=|afilter=|alter|benchmark|chbd|chmod|cmd|command|cast|char|concat|convert|create|db_query|declare|delete|download_file|drop|edit_file|encode|environ|eval|exec|exploit|find_text|fsbuff|ftp|friends_links\.|globals|gofile|grab|insert|localhost|logname|loopback|mail_file|md5|meta|mkdir|mkfile|mkmode|mosconfig|muieblackcat|mysql|order|passthru|popen|proc_open|processes|pwd|request|rmdir|root|scanner|script|search_text|select|selfremove|set|shell|sql|sp_executesql|spicon|ssh|system|telnet|trojan|truncate|uname|union|unzip|whoami) [NC]
RewriteRule .* - [F]

These are a work in progress and will definitely be updated as I encounter and discover other attacks directed towards this directory.

But for the meantime, this will block many shell uploads and other attacks.

__________________________________________________________
# Disable hotlinking of images
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} \.(jpe?g?|png|gif|ico|pdf|flv|swf|gz)$ [NC]
RewriteCond %{HTTP_REFERER} !^https?://([^.]+\.)?yourdomain\. [NC]
RewriteRule \.(jpe?g?|png|gif|ico|pdf|flv|swf|gz)$ - [NC,F]

These disable hotlinking of all images/files from this directory. You may already have this in your root .htaccess. If so and it works fine for you there, they you’ll not need it here. But test to find out for yourself.

You can test if you’re hotlinking is disabled via the following sites:
http://altlab.com/htaccess_tutorial.html
http://techgyo.com/HTML-Editor.htm

__________________________________________________________
Order Allow,Deny
Deny from all
<FilesMatch "\.([Jj][Pp][Ee]?[Gg]?|[Pp][Nn][Gg]|[Gg][Ii][Ff]|[Gg][Zz]|[Pp][Dd][Ff])$">
Allow from all
</FilesMatch>

The next rules only allow certain file extensions, case insensitivity included.

__________________________________________________________
<FilesMatch ".*\.([^.]+)\.([^.]+)$">
Order Deny,Allow
Deny from all
</FilesMatch>

These last set of rules get interesting. Suppose someone does actually get a double extension uploaded? Even if you have php to assign an additional character to the end of the first extension, an attacker may be able to acknowledge that they were successful at uploading the file by adding that character when trying to execute it.

Example: I believe WordPress adds an underscore to the end of the second extension. So an attacker uploads a script.php.jpg. WordPress converts it to script.php_.jpg. If an attacker knows this, they may be able to account for it and still execute the attack.

What this does is block any extensions with character(s) represented by a ‘[^.]’ that are 1 or more characters in length with a double extension ‘\.’

This is because the characters could be anything besides a letter or number and if the attacker knew that you appended an underscore ‘_’ or any other character, they could continue with the attack. You can always change the number 10 to fit your needs. You could also change the second ‘.’ to this [a-zA-Z0-9] but it seems to be more efficient to just use ‘[^.]’.

**NOTE** I’ve had sites where I had to change the second ‘[^.]’ to [a-zA-Z0-9] to allow users to still upload files.

# Block double extensions from being uploaded or accessed
<FilesMatch ".*\.([^.]+)\.([a-zA-Z0-9]+)$">
Order Deny,Allow
Deny from all
</FilesMatch>

This last set of rules only allows the GET and POST HTTP methods.

</FilesMatch>
<LimitExcept GET POST>
Deny from all
</LimitExcept>

Back to Top

Advertisements
Published in: on July 24, 2011 at 2:04 pm  Comments (2)  

The URI to TrackBack this entry is: https://tomolivercv.wordpress.com/2011/07/24/protect-your-uploads-folder-with-htaccess/trackback/

RSS feed for comments on this post.

2 Comments

  1. […] online. Updating your .htaccess file will prevent online users from viewing this folder too (read here for more […]

  2. […] to be able to view images when coming to the site, I utilized the code shared by Tom Oliver in his protecting uploads with htaccess. By replacing the deny from all code with the code Tom provided in his post, security of the […]


Comments are closed.

%d bloggers like this: