I have an application that let users to upload files to server. All files are stored in one directory called Uploaded Files (which has Thumbnails directory inside).
What are the most common ways for preventing users to see these files ? I mean I don't want users to see the files by typing URL like /path_to_website/Uploaded Files/1.png.
On the other side, authorized users should be able to see the files by getting a page that contains paths to files, like: ../Uploaded Files/1.JPG, ../Uploaded Files/2.png, ../Uploaded Files/3.gif. These users should be able to see only the files that appear on the page they got, i.e. I want to prevent them to see ../Uploaded Files/823.gif for example.
Please help to understand how this kind of things are done these days.
Thanks a lot !!
You can move the images into a folder out side the public directory and then stream them in via PHP to the users who are allowed to view them. By using the method detailed in the PHP header() manual for a very basic output (see Example 1).
Otherwise you could put a .htaccess file in the folder containing:
deny from all
if you are running Apache, but you still need to stream it out through PHP.
Related
I am currently busy with a website which basically does the following:
someone uploads a file then some processing is done on that file and then the completed file is stored in a directory called /documents.
Inside of my php script I generate a random number which allows multiple documents to be stored simultaneously, for example a document might be stored in /documents/145214693/file.pdf.
The user then has the option to download the document.
Inside of my /documents folder I have a .htaccess file which Deny's anyone to access the /documents folder by typing it into the URL bar, for example when someone types www.example.com/documents/ they will receive "Forbidden".
Now the issue is, this also disallows anyone from downloading the file.
Is there a way in which I can generate a random code and inside of my htaccess file I specify that only someone with that specific code is allow to access that specific directory?
In short, when someone uploads a file it is stored in /documents/256984128/test.pdf, then generate a random code which is passed through the URL for ex,
www.example.com/documents/256984128/test.pdf?code=<random code here>
and only if the code is correct access is granted to the file.
Thanks in advance!
I have a folder where I have some protected files (or files i'd like to protect). In order to access the files you must first log-in. I recently realized that when you type in www.mysite.com/myprotectedfiles/admin/ you can preview the list of files and even click to them.
Even though you can not access the information, the fact that you can view the folder contents somewhat bothers me. Is there a way to make folder permissions where you can't navigate to these folders without hitting our login.html page first?
Any help with this would be great.
Sounds more like a web server issue rather than a PHP one. If you're saying I can browse to a folder and then get a listing, then (at least in the Apache world) that is the DirectoryIndex that you would need to shut off.
After that you should be good. Depending on how the rest of your admin site is set up, you may need to either put a session check (or how ever you're tracking the logged-in state) in each of your file and if you have other file types (doc, xls, pdf, etc) you may need to put them in a non-web accessible directory and then have some code that will read the contents of the file into a buffer for download, if you don't want someone to be able to directly browse to the files.
I created an index file for ea folder with a redirects to my login page instead. Its diffucult to get my IT dept to turn off directory listings so this was a fair workaround.
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.
I have a directory of files that logged-in users can upload to and access. Some of the files are public, and others are private - for internal access only. The filenames and access settings are saved in a database.
Can anybody give me some resources or show me an example of how i can use session data (and .htaccess?) to allow access of private files only to authorized users?
I'm thinking it might be easier to keep public documents in a seperate, unprotected directory, though i'd kind of like to keep everything together.
I'm not concerned about top-level security or encryption, as the files aren't terribly sensitive, but i want to keep them from being indexed on search engines, etc.
thanks!
I suppose I wouldn't use a .htaccess (or any kind of HTTP-authentication) for that : .htaccess / .htpasswd are great when you want to allow/deny access to a whole directory, and not to specific files.
Instead, I would :
Deny any access to the files -- i.e. use a .htaccess file, containing Deny from All
That way, no-one has access to the file
Which means everyone will have to use another way to get to the files, than a direct URL.
Develop a PHP script that would :
receive a file identifier (a file name, for instance ; or some identifier that can correspond to the file)
authenticate the users (with some login/password fields), against the data stored in the database
if the user is valid, and has access to the file (This is if different users don't have access to the same set of files), read the content of the file from your PHP script, and send it the the user.
The advantage is that your PHP script has access to the DB -- which means it can allow users to log-in, log-out, it can use sessions, ...
About the "send the file from PHP", here are a couple of questions that might bring some light :
Sending correct file size with PHP download script
Resumable downloads when using PHP to send the file?
forcing a file download with php
I'd create a custom index script in PHP -- something that would show the files dynamically. Use that to keep only the right files being listed -- afterwards, to further protect the files, fetch file contents dynamically -- Pascal MARTIN's links show you how to use PHP to control the file streaming, you can use that to block access from hidden files to users that aren't supposed to get to them.
I am trying to secure my PHP Image upload script and the last hurdle I have to jump is making it so that users cannot directly excecute the images, but the server can still serve them in web pages. I tried changing ownership and permissions of the folders to no avail, so I am trying to store the images above public_html and display them in pages that are stored in public_html.
My File Structure:
- userimages
image.jpg
image2.jpg
- public_html
filetoserveimage.html
I tried linking to an image in the userimages folder like this:
<img src="../userimages/image.jpg">
But it does not work. Is there something I am missing here? If you have any better suggestions please let me know. I am trying to keep public users from executing potentially dangerous files they may have uploaded. Just as an extra security measure. Thanks!
You want something that's basically impossible.
The way a browser loads a page (in a very basic sense) is this:
Step 1: Download the page.
Step 2: Parse the page.
Step 3: Download anything referenced in the content of the page (images, stylesheets, javascripts, etc)
Each "Download" event is atomic.
It seems like you want to only serve images to people who have just downloaded a page that references those images.
As PHP Jedi illustrated, you can pass the files through PHP. You could expand on his code, and check the HTTP_REFERER on the request to ensure that people aren't grabbing "just" the image.
Now, serving every image through a PHP passthru script is not efficient, but it could work.
The most common reason people want to do this is to avoid "hotlinking" -- when people create image tags on other sites that reference the image on your server. When they do that, you expend resources handling requests that get presented on someone else's page.
If that's what you're really trying to avoid, you can use mod_rewrite to check the referer.
A decent-looking discussion of hotlinking/anti-hotlinking can be found here
Use an image relay script!
To serve a imagefile that is outside the public_html folder you would have to do it by a php script. E.g make a image-relay.php that reads the image that is outside the public html...
<?php
header('Content-Type: image/jpeg');
$_file = 'myimage.jpg'; // or $_GET['img']
echo file_get_contents('/myimages/'.$_file);
?>
Now, $_file could be a $_GET parameter, but its absolutley important to validate the input parameter...
now you can make an <img src="image-relay.php?img=flower.jpg"> to access a flower.jpg image that is located in /myimage/flower.jpg ...
Well, a web browser will only be able to access files and folders inside public_html.
If the public_html directory is the root of the server for your users, Apache cannot serve anything that is not inside/below that dorectory.
If you want a file to be served by Apache directly, you'll have to put it in/below public_html.
I think your misunderstanding is in the fact that if you include an image in an <img> tag, your browser will send the exact same request to the webserver to fetch it, that will be sent to the webserver if you try to open the src url of the image in your browser directly.
Therefore, either both things work, or neither.
There are hacks around, involving a (php or other) script to make sure that an IP that has requested the image has also requested the html page within the last few seconds (which will not work if the user is behind a proxy that rotates outgoing IPs) or by checking the referer (which does not work with HTTPs and also not if the user has referer disabled).
If you want to make sure that only some users can see the image (both via <img> tag and directly), you can put the image outside public_html and have a (php or other) script that verifies the user's credentials before serving the image.
If you are using Apache or lighttpd you can use the X-Sendfile header to send files that are not in the web root(provided you haven't changed the configuration of mod_xsendfile).
To learn more about X-sendfile see this site.
This solution is giving you the best possible performance as PHP doesn't send the file but the server does and therefore PHP can be exited while the files are being served.
Hope that helps.