direct file download protection - php

I have a folder for downloads on my server, i want to prevent direct access to that folder so i am makin it pass-protected with htaccess and i will push download with a php script. But i have some questions regarding mkdir and file_exists
Do mkdir and file_exists works good for pass-protected folders ?
and
would i get any error while uploading file to that folder ?
AND
is this a good way of preventing direct access ?
thanks

As pass-protection only aplies to HTTP connections though your Apache server, every PHP function that can access files will work. And because uploading a file is also only copying a file with PHP from the temp dir to the upload dir, there should be not problem.
Using htaccess is a good method to avoid direct access. But it would be much better to have the uploaded files in a directory which can not be access through any HTTP reuest. So storing it above the httpdocs (or equal) folder will make it totally impossible to access a file through a direct request.

htaccess works fine for simple password protection. As soon as a user has authenticated everything works exactly like for normal folders. It should not affect any php-functions or server side permissions.

Related

How to safely upload and download PDF files stored in the file system using PHP

I've tried to look around for some tricks on how I can do this safely, without executing the code.
Does the code get executed if i simply upload it to the file system, then leave it be until someone downloads it?
Or is this a potential threat aswell?
What I am trying to do is making the users able to upload their CV in pdf files. The administrator can then download this pdf file (not being viewed on server, but downloaded).
How should I do this to prevent malicious files from being executed on my server? Also, would it be risky to place this folder OUTSIDE the public_html folder?
There's not a lot of risk to upload .pdf in a folder.
the folder must be in 644 (chmod). and have a index.php with redirect to the index of the website
Inside or outsite the "public_html" .. it's not a problem
when you upload, you can check the extension (.pdf) and type mime:
with finfo_file (http://php.net/manual/en/function.finfo-file.php )
and
with $extension = substr($file, -3);
That depends on how your server is set. If it allows PDF files to be used as executable, or to be opened with particular application/processing script that could be used for malicious actions. Otherwise you have to follow simple instructions such as restriction of file name length and avoiding to perform read operation of that file. As I understand you need only to upload and safe them. I'd keep them in public_html and once uploaded correctly (you checked filesize, extension etc) moved them whenever you like.

File location issue

I'm having trouble putting data in safe locations. What I want to do is allow my localhost to access the files to create my pages but prohibit all other access.
I started out trying to write a .htaccess file to prevent access to subfolders but read here that this was a poor way to do things and was getting into a tangle anyway so, following advice, I tried moving the files out of the public_html directory:
The structure is:
bits_folder
images
testimage.jpg
files
testfile.php
public_html
application
callingfile.php
With this layout, I get error 404 if I try to access anything in bits_folder from the browser, as desired. callingfile.php however does not seem able to access the testimage, but can include the php testfile.
callingfile.php:
require("../../bits_folder/files/testfile.php"); //works and displays file echo
<img src="../../bits_folder/images/testimage.jpg" //gives broken image
both the files (testimage and testfile) are in the folders where they should be.
I am assuming that the reason for this behaviour is that the img is a http request after the page is served and will thus be denied but I am no server expert. Is this the case? Can this be overcome? Should I be doing this another way?
Only place scripts and images for PHP to use outside public_html. Images and other things that are as src or otherwise linked in HTML/JavaScript cause the browser to request those. The web server will refuse to serve them from outside the public directory.
Your browser will get access denied for www.example.com/../../bits_folder/images/testimage.jpg

PHP uploader and htaccess password problems

I've got a rather baffling question/problem, let me lay it out for you.
I have two directories -- gallery and uploader
The uploader directory is htaccess password protected. This is where several PHP pages and the PHP file uploader reside. I enter my credentials when I access the index PHP file when I load a the index within the directory.
The problem is that the uploader is uploading the files and then moving it to the gallery directory (not password protected). It then runs other scripts to copy that image, resize it, then delete the original. This process works beautifully until I put the htaccess password on the uploader directory. So for some reason the PHP uploader in a protected directory can't move/work on the uploaded image and then copy it to the un-protected directory.
Any ideas of what I need to do? I'm not sure if the issue is the PHP uploader calling other scripts in the protected directory or if it's having troubles when moving it to the un-protected directory.
EDIT:
Here is some sample code and as you can see URLs aren't being used (nor are they in the resizeMyImageTN method).
//WHERE THE SAVE HAPPENS!
move_uploaded_file($_FILES['Filedata']['tmp_name'], '../../uploads/'.$folder.'/'.$new_index.'-' . $_FILES['Filedata']['name']);
//Call function to resize images pass in path
resizeMyImageTN($_FILES['Filedata']['name'],$folder, $new_index);
unlink('../../uploads/'.$folder.'/'.$new_index.'-' . $_FILES['Filedata']['name']);
.htaccess protection works at the webserver level. But, UNLESS you're using URLs in your various file-manipulation calls, the PHP script works at the filesystem level and would never see the .htaccess protection.
move_uploaded_file($_FILES['uploaded']['tmp_name'], '/some/dir/that/is/protected/newname.txt');
would not involve the HTTP layer, which means no protection. But if you were try
move_uploaded_file($_FILES['uploaded']['tmp_name'], 'http://myserver.com/newname.txt');
that would involve a new HTTP request, re-upload the file, and be subject to any URl restrictions in place on the server.
Without seeing some code, we most likely can't answer your question.
I forgot to answer this (my bad). In the end I could only get it to work by not having the upload directory .htaccess protected. Which wasn't ideal but I couldn't seem to figure anything else out. Since I asked this I have converted the site to Django and that has fixed all my problems.

Securing upload form at php

I am making a feature to my site so that users can upload files (any type).
In order to secure the upload form, i made a blacklist of non-accepted filetypes. But in order to assure protection to my server (in case of uploading malicious scripts in any way) i thought to tar the uploaded files (using the tar class) so that they are stored as .tar zipped files.
So if the user wants to donwload it, then he will receive a .tar file.
My question is, is this secure enough? (since the files cannot be executed then).
[I have this reservation as i can see at the code of tar class, the "fread()"]
Thanks!
Two points, here :
Using a blacklist is a bad idea : you will never think to all possible evil filetypes.
Do not store the uploaded files into a public directory of your server :
Store those files to a directory that is not served by Apache, outside of your DocumentRoot.
And use a PHP script (even if Apaches cannot serve the files through HTTP, PHP can read them) to send those files contents to the user who wants to download them.
This will make sure that those uploaded files are never executed.
Of course, make sure your PHP script that sends the content of a file doesn't allow anyone to download any possible file that's on the server...
You can upload the files to an non web accessible location (under your webroot) and then use a download script to download the file.
The best way of handling uploaded files, in my opinion, is to place them in a folder that's not reachable through HTTP. Then when a file is requested, use a PHP file to send then download headers, the use readfile() to send the file to the user. This way, files are never executed.
That might work, assuming that you're users that will download the files can untar them (most non UNIX systems just have zip, I'd give them the option to download either format).
Also, i think its better to create a list of allowed files vs banned files. Its easy to forget to ban a specific type; whereas you will probably have a better idea of what users can upload
Dont block/allow files on extension. Make sure you are using the mime type that the server identifies the file as. This way its hard for them to fake it.
also, store the files in a non web accessible directory and download them through a script.
Even if its a bad file, they won't be able to exploit it if they can't directly access it .
When saving the files make sure you use these functions:
http://php.net/manual/en/function.is-uploaded-file.php
http://php.net/manual/en/function.move-uploaded-file.php
Dan

PHP - Question about uploading & uploaded image file

I have read the following tutorial "Uploading Files To the Server Using PHP"
and have several questions related to the topics.
Q1> The tutorial mentions that
"Note that PHP must have write access
to $uploadDir or else the upload will
fail"
For me, I only allow the user to upload the file after the user has login to the website.
If we set that $uploadDir permission as 777, then everyone can have written permission to that folder. How to avoid this problems?
Also I am using WAMP as my testing bed, can I simulate the same case as a real web server?
Q2> In order to prevent Preventing direct access, the tutorial mentions:
"A better approach is to move the
upload directory away from your web
root. For example, the web root for
this site is:
/home/arman198/public_html/ to prevent
direct listing i can set the upload
directory to /home/arman198/upload/."
Now my problem is that how can I display the uploaded images on other website pages. Since, the upload is not accessible directly anymore? I need to display the uploaded image save personal headshot dynamically on other website page. Is it possible?
Thank you
It's a common problem.
All modern computers have a temporary files directory. On Linux/Unix it's /tmp, on Windows it's usually c:\temp. The OS install will have set permissions on that directory so that anyone can write files there but only privileged users can delete files that don't belong to them. This is where PHP will want to put an uploaded file; your application then has to move it elsewhere (this is the purpose of the move_uploaded_file() function). PHP under Windows may need upload_tmp_dir actually set in the php.ini file.
Once you have an uploaded file, you can shift it whereever you like, including to where the webserver can read it to serve it. The biggest problem with that it is awfully easy to put this directory inside your codebase. Don't do that. As soon as you do anything beyond editing the files inside the directory they are served from, it will be problematic. Trust me: I've dealt with a few times this in code I've inherited. It's easy to let your webserver load files from a location outside your codebase.
The other alternative is to produce a download script. That way the file need not be servable by the webserver at all. One disadvantage is that you don't get to leverage the web server's MIME translation, but then, that lets you control which types of image files are permitted.
For the second question, you can use a PHP script intead of direct access to the directory. Lets name it image.php. Lets assume that it can take a parameter id, like image.php?id=image_id. In that file you can get the id using superglobal array $_GET. Then you can search for images with that Id and just send it as response.
First one I'm not sure, but maybe play with .htaccess file.
And for the first question, try setting your permissions to 775. That should allow PHP to write the file to the directory without giving the general public write access.

Categories