Score:12

Is this a good practice to upload files to a folder outside the public www folder?

gb flag

I have a web site where users can upload files. I do not want those files to be accessible by anyone.

I have seen that some people create a folder (say my_secret_folder) at the same level of the www directory. Then, they upload files (with PHP script) using:

$destination = $_SERVER['DOCUMENT_ROOT'] . "/../my_secret_folder/" . $filename;

Where $destination is the full path of the uploaded file.

Then, only the PHP script (from within the www folder) is allowed to access the file. Is this a good practice to upload files to a folder outside the public www folder?

Voo avatar
in flag
Voo
Just remember when doing this you have to be very, very careful about `filename` - e.g. `..\look_where_i_am` has been a security vulnerability for decades.
Score:29
ar flag

Yes, it is a good practice. Placing it outside the webroot means that the files will not be publicly exposed by a simple configuration mistake in the web server, thus adding another barrier to exposure - and it has essentially zero cost to implement.

mx flag
And even if they are intended to be publicly exposed, this is a reasonably good practice, because it lets the server control when and how the file gets exposed in a much simpler way than would be the case with uploading directly to the final location. This is especially important if the files need to be processed in some way before public exposure.
Score:3
jm flag

Assuming that this is an apache server, have your considered placing restrictions on the directory?

<Directory '/var/www/html/uploads'>
    Options -Indexes
    <Limit GET>
        Require user admin
    </Limit>
</Directory>

Don't show a list of files if somebody tries to browse the directory and limit an HTML GET to somebody logged in as admin.

HSchmale avatar
dj flag
I would have to say hard disagree. Even if you have this, there's no guarantees that configuration won't be lost or deployed. It's much safer to keep it out of the webroot.
jm flag
@HSchmale If having the configuration changed is a concern then can you be certain that DocumentRoot won’t be changed? Or possibly a new admin will not know why the directory is where it is and move it? Put the directives in the config file and document it.
GACy20 avatar
md
@doneal24 Yes, but I'd argue that it's probably an easier mistake to make to modify any point in the configuration you provided and break it (thus failing to apply the restrictions) than to have someone 1) accidentally modify the webroot 2) have the website still working somehow and 3) have the new webroot include also the other directory. That would require an *intentional* change. Obviously these kind of decisions, like everything security related, should be documented somewhere.
Score:2
nl flag

This has already been hinted at in a comment by @Voo, but this point is so important that I think it should be moved to an answer box.

$destination = $_SERVER['DOCUMENT_ROOT']."/../my_secret_folder/".$filename 

This is good practice, if, and only if, the web user cannot control $filename. Otherwise, it's a path traversal vulnerability.

Consider what happens if the client crafts a special request where $filename is ../www/index.php. You just allowed your uploader to overwrite your web application's code.

Resist the temptation to solve this issue by blacklisting values such as / and ..: there are ways around that, the link above lists a few. The canonical solution to this problem is to either (a) choose the file names yourself or (b) have an explicit whitelist of allowed characters.

chaL67 avatar
gb flag
In my case, the user uploads a file with an Ajax request that calls a PHP script. This scripts then changes the filename to 'toto_id' where id is the user id and 'toto' is a string I have chosen. Finally it moves it to the 'secret' folder. Is the attack still possible ?
chaL67 avatar
gb flag
... and the extension of 'toto_id' is set to .png only.
nl flag
@2WFR: Sounds good to me.
chaL67 avatar
gb flag
Obviously the user can check if his uploaded file is ok. Here the php script that reads the file has the user id as an input (not the file name as it is always ´toto’). But then it is easy to check that the id corresponds to the user with a valid php session.
Score:0
cn flag

I would argue that this is not a good practice. The security risks that @Heinzi pointed out are very real, but even if you do everything correctly security-wise, you still have end up having a bunch of [presumably important] user files stored on your server. Servers should ideally be ephemeral. There are much better solutions for storing files than just having them lie around in your server. Even if you are taking automated backups (are you?), your setup for them is probably nowhere near as robust as it ideally could be.

I'd advice you to for example look into AWS S3 or Google Cloud Storage, these kind of managed file storage solutions are extremely cheap nowadays and take care of all the hazzle for you.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.