.htaccess allows images only - php

I know similar questions have been asked, but none of it guided me to the right solution.
What I want to do
Use .htaccess in a /uploads folder to ensure that only file with appropriate extension can be uploaded. (e.g. jpg, png)
What I have done
modify /etc/httpd/conf/httpd.conf
to allow overwrite of .htaccess file
create .htaccess file in /uploads folder
To test if .htaccess has been read, I have tried to put garbage in .htaccess file and access it from the browser. Corresponding error has been generated, therefore, .htaccess file is working properly.
Problem
The following script has been added to .htaccess
order deny,allow
deny from all
However, I am still able to upload files with any extensions to /uploads folder.
I have tried different suggestions from similar posts with no luck. Looking for new directions from you guys.
Thanks.

The name of the uploaded file is part of the body of the POST request the browser is making to the server, thus the .htaccess rules can't be enforced in your situation. Unless you are using some uploading schema, like creating a placeholder on the server and then submitting the file to that placeholder.

if you are using a GET method with base64 encoded string in your url, you can use .htaccess to redirect to an upload script base on the mime-type of that string. however I guess this is not what you trynna achieve. .htaccess is not appropriate in your case. if you need to control the extension of an uploaded file, you should make the process directly in your uploading script (php, python, whatever).

Related

Prevent .htaccess files within subdirectories from being executed

I have a service where a user is allowed to upload anything they please. I have code execution and others disabled, but I cannot find a way to prevent a .htaccess file they upload from executing.
You should always rename user uploaded files! If you do not do that, user can easily upload hack.php and then launch it to get your site hacked or abused. So this is in fact your problem.
Rename your files after upload. Keep original name (along with i.e. size, mime type etc) in database and route file download/view via the script which would take that original name from DB and build proper headers and then file() content of that file to the user. That would prevent a file from being executable on your server
Or if that's the problem with .htaccess only (but I dare to say it is wider) then you can configure apache to ignore .htaccess in certain directories. It requires root rights on the machine, but you can add <Directory FOLDER> block to host configuration and put AllowOverride None in it.
Or, just check target filename on upload and reject any .htaccess and .htpassword. Or anything with name starting with .

How can I protect a PHP image upload script from exploits?

I've created (using a script and some help from Stack and some help from friends; I know very little about PHP) a simple page for a local non-profit publication where people can upload photos.
I'm not great with security (from a basis of ignorance, not deliberate negligence) but I've taken the following steps to protect this page:
• the PHP script is set to only accept .jpg, .png and .tif files for upload;
• the subfolder that it saves the form content to has permissions set at 700, and the subfolder it saves uploaded photos to has permissions set at 700;
• according to documentation, my host has the following configuration to ensure that only .php files run as .php:
<FilesMatch \.php$>
SetHandler php52-fcgi
</FilesMatch>
• I’ve put an .htaccess file in the relevant (main and saved content) folders:
RemoveHandler .php
RemoveHandler .inc
RemoveHandler .pl
RemoveHandler .cgi
RemoveHandler .py
RemoveHandler .fcgi
Overnight, however, somebody found this test page and submitted what seems to be a perfectly benign test message and small .jpg. This is a private test page with a non-intuitive URL that only I and about three other people know about; none of the others sent this test.
This obviously has me worried that there's something hinky going on, and I'm worried that I don't know enough about security to make sure this page is safe.
Is there something obvious that I'm missing?
When dealing with uploaded you should keep in mind that all the data you can find in the $_FILES array can be faked. It's traveling through HTTP so it's pretty easy to give the image/jpg mime to an executable file for exemple.
1- Check the true mime
PHP come with some function to check the real mime of a file. For that you should use fileinfo
$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
$filename = "/var/tmp/afile.jpg";
echo $finfo->file($filename);
2- Check the image's properties
You apparently want to upload only image , so the received file must have a width and a height :
Use getImageSize() to get all the required information about the image. If it return false , the file is probably not an image and you can delete it.
getImageSize can also give you a mime type , but i don't know if it can be trusted.
2.5- Reprocess image
As suggested by user628405 , reprocessing the image with GD is probably the more secure thing to do.
$img = imagecreatefrompng('vulnerable.png');
imagepng($img, 'safe.png');
Obviously it has to be adapted according to the image type. See all the imagecreatefrom* in php documentation.
3- Upload folder
In addition of what you have already done :
Make sure your upload folder is not available from the web. Validate the uploaded file then move it to an other folder if needed and rename the file.
It will prevent hacker from executing a malicious file (can't execute it if it can't be reached by an url).
Further reading : https://www.owasp.org/index.php/Unrestricted_File_Upload
Don't rely on any data from the client, including content type!
Don't save uploaded files in the web root. Uploaded files should be only accessible via your scripts, for better control.
Don't save uploaded files with their original file names and extensions! Store this data in a database for retrieval later.
You can check the MIME type of the file, but don't worry as long as your php handler can only execute .php files and you're taking care of not saving uploaded .php files in your script, you're not exposing any security leak.
This is valid for .php files as well as any other server-side scripting language installed on your server of course.
A better idea is to keep a white of the extensions you're accepting to save on your filesystem.
I would ignore the MIME type and the file extension of the incoming file. These can be faked.
Store those files in a directory if you are going down that avenue.
Ensure that that directory is just for images (music) and then get a script to place the correct extension on them by looking at the files format.
Also ensure that that directory cannot execute PHP (or anything else).
This will keep you safe.

Uploading and displaying .html files in browser

I'm working on a little project with a few friends, and have set up a pretty simple PHP upload script that only certain users can access. I am not worried about any type of attacks against the server, since this is for fun, but I do have a question.
I've made a subdomain (static.foo.bar) where the uploaded files are moved to. This subdomain had mod_php turned off, to prevent malicious upload and execution of php scripts. The script also checks for file extensions and mime content types, but I assume those can easily be bypassed/spoofed.
However, a user could easily upload an .html file and have it redirect somewhere else. Likewise, they could upload an image file instead and have it display an image in the browser, instead of being asked to download the image.
I assume this is the behavior of the browser, but I've also noticed that when uploading a file to sendspace (or any other service), even if the file is .html (and valid html) it will ask the user to download it instead of displaying it on the website.
I am running Apache on CentOS.
How do I accomplish this?
ForceType is probably what you're looking for.
# In your .htaccess file
<Location /uploads_directory>
ForceType application/octet-stream
</Location>
You want to set all files' mime type to application/octet-stream so the browser will download them instead of trying to show the content.

PHP remote access to .htaccess protected files

I'm having a bit of trouble trying to access the content of .txt files on a remote server that are in an .htaccess protected directory.
What I am trying to do is the following:
Connect to the FTP server via PHP and use ftp_nlist to retrieve a list of all the .txt files in a directory. Up to here, everything works fine.
For each .txt file found, I want to retrieve the contents. There are a number of ways to do this normally which all work fine when there is no .htaccess file protecting the .txt files.
BUT! As soon as I protect the online directory with the .htaccess file, every single method I have tried fails to get the contents of the .txt files. The .htaccess file that is protecting the folder that contains the .txt files has the following (and nothing else):
<Files *.txt>
Order Deny,Allow
Deny from All
</Files>
Obviously, the online PHP website itself can access the contents of the .txt files without any problems, and the .htaccess file itself is doing it's job perfectly (denying direct access to any of the files), but when I'm trying to access the .txt files remotely from my WAMP server, I just can't find a way to bypass the .htaccess protection.
Basically, I want to imitate remotely, from my WAMP server, what my website already does itself locally by using $contents = file($filepath). Surely there must be a way... Can anyone point me in the right direction? Should I be using a different method of protecting the .txt files, or should I be using a specific PHP function to access the contents?
Your question isn't clear.
If you protect a folder or a file with .htaccess you will be still able to download that file with FTP. .htaccess affects only Apache (http requests).
If you want to be able to download those file anyway with http, then you just do a script that outputs its content:
downloader.php:
//> Check if the admin is logged, and check if $_GET['filename'] is allowed
readfile($_GET['filename']);
Then you can request your file with:
http://yoursite/downloader.php?filename=file.txt
Of course be sure to protect the access of this downloader.php

.htaccess for images only upload

I'm developing a very simple PHP upload feature in my site to permit users to upload JUST images. Apart from checking the mime-type through php I wanted a .htaccess file to rule what can be uploaded and what can't.
I want to insert the .htaccess in my root folder and from there writing the rules for all the folders I need to be ruled.
It's the first time I work with .htaccess and from the internet I was able to find this:
http://pastebin.com/0KNHEbw0
But it doesn't work. I'm testing it locally with my xampp on win7 and I see that I can upload any type of files in the "oggetti" folder.
What's that is wrong?
And then, to rule other folders should I write something like this?
http://pastebin.com/dFMUu1g0
Thank you in advance!
You can't control what files are uploaded through a .htaccess file: Apache, the web server parsing those commands, deals with serving the files only.
You will need to do these checks in the PHP script that handles the upload process. Note that checking the MIME type sent with the file is not a reliable method to determine a file's type! The value sent can be manipulated by an attacker. To ensure a file is an image file, you could e.g. use getimagesize().
This cannot be accomplished using .htaccess. I'm guessing what you're trying to do is prevent malicious scripts from accidentally being executed on the server. The way I normally handle file uploads like this is:
Insert filename, mime-type, etc., into a database with an auto_increment ID.
Use the ID as the file name - no extension, and place the file in a directory outside of your webroot. This way you're certain nobody can execute the file.
When a file is requested, query the database for filename mime-type and id, and send the file to the user with readfile() (follow the link for an example).

Categories