Image security and linux file/directory permissions - php

In a PHP app I am allowing users to upload photos. Upon user upload, metadata is stored in the db and images are then stored in a directory on the linux server. I only want these images to be viewable when called through a view so I can verify that the correct party is viewing them. I do not want anyone to be able to just enter a url and view the image.
/site
/framework
/protected /**My PHP site**/
/www
/images /**This is where I am currently storing the images**/
In order to restrict viewing of these images do I need to move the images directory outside of www? If so to where?
What linux permissions should be given on the images directory?
For images that I have stored in my db that I want restricted access to I use access rules within my framework. Can rules such as these limit access to images in a given directory also?
Any info that can be provided as to how to approach this (so I can do further research) as well as answers to the questions above will be very helpful.

For all images in that directory to be denied (they ALL must be access through a script and none of them will have direct access available - ie only your server will be able to access them, and you have apache with mod_rewrite) you can put a .htaccess in that directory like the following:
deny from all
So to answer the questions by number.. ^^
No, the .htaccess will take care of it with the same effect.
You'll need read (+r) for the images for the server.
The framework may have something like that, but it can't prevent direct linking if the image URL is known. Doing it with .htaccess or moving the directory would be the best bet.

In order to restrict viewing of these images do I need to move the images directory outside of www?
No, but that is the most secure option.
If so to where?
Anywhere
What linux permissions should be given on the images directory?
The minimum you need for the server to read from and write to it. Possibly 700.
For images that I have stored in my db that I want restricted access to I use access rules within my framework. Can rules such as these limit access to images in a given directory also?
Since the images are only available via PHP, the PHP can add whatever auth/authz you like.

You could simply use a .htaccess file and restrict people from entering that directory, as well as turn off directory listing just in case.

Related

Accessing folder outside of website root PHP

I am using some shared hosting and have several websites. Root folder for every website is defined on domain manager. What is need, if it possible, to access some images from another folder that is not i root folder of website.
Example
I have some folder structure
example
demo
pictures
- 1.jpg
- 2.jpg
Some website www.example.com is pointed in folder example, but i have some images that are placed in root of my webhosting in folder pictures, folder pictures are not defined with some domain, i can only access them from FTP. For www.example.com website i need to show pictures that are places in picture folder. I know MODx manager works that way, and i think ot is possible, does somebody knows how?
The main problem here is how does PHP run, i.e. under which user.
Case 1: all your sites run as the same user (e.g. miomir:apache).
Then any of your sites can access all data on all of your sites, just by specifying the path, either absolute or relative (i.e. ../../...). To supply that information from the browser side you need to use a script that will take an URL, say img.php?img=nameofimage, and reply with the image taken not from the script's directory but from somewhere else.
You need to verify user parameters to avoid this trick becoming a vulnerability that gives access to everything on your site. For example check that the file exists, that it is in the appropriate folder (strip any other folder with basename() ), and that it is an image (quick way: getImageSize(), which will also allow you to glean the correct MIME type).
Case 2: your sites run with a different user each.
That is, scripts on www.example.com run as exampleuser:apache, www.foo.com is handler by foouser:apache, and so on.
In this case there is nothing you can do by yourself, and if there is, then the same trick would allow you to read any other customer's site, or allow them to read yours. You so don't want to take your custom to such a hosting company: it's a disaster waiting to happen.
There still is something you can do with your host's approval: ask them to change the user on all of your sites so that it is now the same user everywhere. Then apply case 1. Note that this may impact other things such as database connections (if user identity is not supplied directly from PHP, as it usually is). It shouldn't apply to you, most likely it doesn't, but if you hit some troubles that's the likely cause.
On some systems it will be possible for foouser to allow baruser to "sudo" some functions. This usually requires root (i.e. your host's knowledge, approval and possibly work), but in some setups you can do this by yourself. At that point you will be able to run a script with commands such as cat and copy a file to standard output. While possible, it is messy and not really very performant.
A compromise (still requires your host's approval) is to create a user group (miomirgroup), put some users (exampleuser, foouser, baruser...) in that group, then give group read permission to a folder in your own space to group miomirgroup. For that folder only, PHP will behave as if it was case 1.
Images will need to be placed in a public folder to be accessible. You can do this by placing your images in the public folder, or by placing a PHP script in the public folder that retrieve the "hidden" images and deliver them open request.
Example 1 - Images in the public folder
For example, let's say "/public" is our public www-folder and "/private" is a folder on the FTP server that cannot be accessed from the web.
You can access the /public folder:
/wwwsites/mysite/public/images/hello.png
Link to image: <img src="/images/hello.png">
You cannot access the private folder since the web server does not allow access.
/wwwsites/mysite/private/images/hello.png
Link to image: (not possible)
Example 2 - Retrieving "hidden" images using a PHP script
http://php.net/manual/en/function.imagepng.php
$im = imagecreatefrompng("test.png");
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
create a file img.php in the server from which you want to access images
<?php
//add all the image's names to this array for white listing
$images = Array( "1.png",
"2.png");
if(isset($_GET['image']) AND !empty($_GET['image'])){
$request = $_GET['image'];
if(in_array($request,$images)){
header('Content-Type: image/png');
include_once('/path/to/non-root/folder'.$request);
}
}
now you can access the files using some.thing/img.php?image=1.png

Uploading files and keeping them safe

I'm using php and MYSQL. I've created a members area where people can upload important images (basically for financial record). I was hoping to get some advice as to the best way to store these files. What kind of folder structure would be best? Ex domain.com/Files/UserName/RandomGeneratedName/Files.
Also any advice for chmod, .htaccess, .htpassword and any kind of password protection with php.
Thanks in advance.
I would recommend to store them outside the tree. In this way, by default you need to enable access to them, not disable access (just in case you have a bug in your .htaccess/config/code, the access to the files is disabled, not enabled)
Second, get rid of the random directory, it doesn't add much to the security, but it complicates the implementation unnecessarily
You can use php to check the member credentials, put the appropriate headers (mime type for ex., etag, etc.), and serve the file via passthru or something similar.
Best way:
protect the directory with .htaccess
add an index.html to directory "just in case"
use random file names to store them in your directory
use php/mysql to check if user has access rights to your files
example:
You have a file in domain.com/protecteddir/sdjasdu83299sdnYUsb.dat
You can use php/mysql to send to user to a virtual directory to download the file. You can throw the correct file header + file name via php. So even if the file is called sdjasdu83299sdnYUsb.dat the user would download it as "myfinancial.doc"
The user will never know what the real file is located nor its name.
Your .htaccess file should contain:
<Files *>
Order Allow,Deny
Deny from All
</Files>
you could .htaccess for URL Rewriting and get the index.php file (write this code: ) in folder that save your files, so when anyone want to enter this folder:
First: he dont know real address
second: due there is a index.php that offer to home page he could not enter.

What is the best location on server to upload images?

Among many folders available on the server by default like "public_html", "public_ftp" or simply the root, which one is the best to upload and store users' images safely which I can also add a link to mysql db?
If your clients upload images via http form, store it in public_html if they need access it from web.
I recommend you to save the files somewhere in "public_html" and create the following file to restrict public access:
file: upload/.htaccess
deny from all
In your php script you can send the files only to the users with access.
In my opinion, store it outside of the public htdocs folder. This is so that if someone manages to upload anything other than an image file (such as an evil PHP script), they won't be able to call it (and it won't run).
If you're public_html folder is say /path/to/website/public_html I'd store them in /path/to/website/uploaded_images
Also, make sure you that validate it so that it uses a white-list of allowed image names (such as only allowing .jpg, .gif and .png)
Edit:
You also need to create a script which opens the image file and passes it through back to the user
Define safely.
If you want to display these images on a site, that will be a folder in public_html, obviously, unless you want to use a script which presents the images to the user, possibly altering the image on-the fly, changing cache headers etc. Then you may move that folder outside of docroot anywhere the script will have access to those files.
Personally I store user images, files and everything in docroot, protected by .htaccess and accessed via a script which handles user permissions, if necessary. The files reside in an /uploaded folder with subfoldering up to 2 levels deep, each 'level' storing up to 1024 dirs/files. Files are named by their ids only, without any extension, all file info is stored in database. Took me some time to implement, but thankfully this is a reusable code.
Any folder inside your document root is fine. If you want it to be secure, make sure your script accepts only allowed file typed and, as another measure, put an .htaccess file inside that folder:
<FilesMatch "*.php">
SetHandler None
</FilesMatch>
This will ensure nothing get's executed from inside this directory.

How to prevent users from accessing files on server?

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.

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