Securing image upload directory via htaccess

Hi there folks!

I’ve got an image upload script (the php class I’m using can be found here) and I’m following a security how-to ([URL=“https://www.acunetix.com/websitesecurity/upload-forms-threat/”]found here ) and have gotten to the point in which I need to secure the upload directory from double extensions and disallowed files via htaccess. I’ve tried using the htaccess that they’ve provided, but it has broken the avatars stored in the directory.

Here’s the htaccess they’ve suggested:

deny from all
<Files ~ "^\\w+\\.(bmp|gif|jpe?g|png)$">
order deny,allow
allow from all
</Files>

(NOTE: that I’ve added the bmp extension)

My upload directory is located in /webroot/images/uploaded and I’ve placed this htaccess file in /webroot/images. Upon uploading the .htaccess file, access to /webroot/images/uploaded/2-1408632171.jpg was broken with a 403 forbidden error.

Could someone help me tailor this to my needs? I’m trying my beast to learn how to secure my script, but I’m stuck on this one.

Thanks for your time!

If you are allowing user uploads you need a bit more than that and as long as you rename the files the double extension should be wiped out - have you tried uploading one?

I have been looking into it recently and amongst other things you need to stop php being run in the folder as users can imbed php code into the jpg files; I am not sure about some of the other image types.

I used the .htaccess file from this site

Even if you resize the image the php code will remain in the file, there are a couple of tricks to remove it. With GD you have to do something like read the file and rewrite it - search Google for removing php code from an image - and with imagemagick you open the file use -strip and save it again. This will remove the colour profile as well which could be a problem.
But if you are stopping php from being run in the folder with your .htaccess file it should be OK?

Holy cow, I was way off! Thanks very much for the link.

From reading the links provided, I’ve altered the options of the upload class. First, I’m converting everything to a jpg(it’s an avatar upload system). Also, I’ve disabled overwriting. The filename becomes the user’s ID with microtime appended, so there should never be conflicting names but if there is, the upload class automatically renames. I did move the .htaccess file back from the parent directory to the upload directory, since (if I’m reading it write), the file is now protected from being overwritten. I did this so I could restrict everything but .jpg, which the script is converting all uploads to.

Does this seem like I’ve done my due diligence or am I still missing something ( or more likely, messing a step up)?

Here’s the htaccess file, as I’ve modified it:

# 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} !^(70\\.197\\.161\\.80)
RewriteCond %{HTTP_HOST} !^(127\\.0\\.0\\.0|localhost) [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\\.)?schw\\.im/ [NC]
RewriteRule .* http://schw.im/ [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?)$ [NC]
RewriteCond %{HTTP_REFERER} !^https?://([^.]+\\.)?schw\\. [NC]
RewriteRule \\.(jpe?g?)$ - [NC,F]
 
# Only the following file extensions are allowed
Order Allow,Deny
Deny from all
<FilesMatch "\\.([Jj][Pp][Ee]?[Gg]?)$">
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>

Thanks again for all your help!

It looks OK to me but I am new to this as well.

It was also an eye opener to me as I did not know about most of the hack methods. I have not accepted user uploads before but the site I am working on now will.

The only problem I can see is you can not have transparency with jpg and some users may have an avatar with transparency?

A great point. I can convert to png via the upload class as well . I’ll check and see if gif > png conversion keeps it’s transparency. If so, I’ll change the avatars and htaccess to that, I think.