Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there a way to restrict directory content by the file type?

For example, I have an upload directory that I only want users to put images in, could I go a step further & actually put a restriction that will only allow images in it?

I thought about a CRON Job to check the file extension but wondered is there was another way....

share|improve this question

1 Answer 1

up vote 8 down vote accepted

There are a number of problems with trying to enforce this "after the fact" using a cron job or similar:

  1. Race condition. Regardless of which method you use, if you have some program or some code that will be looking through the directory and may pick up and use files you don't want it to interact with, the only way to actually prevent it from doing that is to either (1) code it up that way (or modify the existing source code if it's open source); or (2) don't allow the files to be placed in that directory in the first place.

  2. You didn't state which OS you're running, but on Linux, you could somewhat efficiently use fanotify to monitor file creation/renaming within the directory, and take action whenever a disallowed file is created or renamed to a disallowed name or contents. Of course, this is inherently a race condition, so if you have other code that will be accessing the directory while "users" (other programs or user accounts) will be placing files in there, it is impossible for you to absolutely prevent those files from being picked up (and possibly read, before your code has a chance to delete/move them).

What I would suggest is this:

  1. Create a new group, or use an existing group, whose only members are users you trust not to run any programs that will place the unwanted files in that directory.

  2. Set the permissions on the directory to something like 770 or 775 and set the group and user owner appropriately, using chmod and chown, respectively. This will prevent users outside of that group from accessing (resp. writing to) that directory, so the program(s)/user(s) which you don't trust to place the correct files in there will be excluded from doing so by the discretionary access control mechanism of the filesystem. This should work on almost any UNIX-alike (even Windows, but the permissions system is slightly different there). Just make sure you aren't storing this directory on ntfs-3g or some other filesystem that ignores discretionary access controls.

  3. Write a program, or use an existing program, that provides a service (a web service, a UNIX domain socket, or something) that will accept file content along with a file name for "upload". This program should then receive the entire file from the user, store it in RAM or a temporary folder until it's fully downloaded, then examine the file name and contents to make sure that files of the undesired file type throw an error, and are not placed in the directory. If the file appears fine, you can write the file contents to the desired file name in the restricted-by-group directory mentioned above.

For the "use an existing program" component of the above paragraph, I googled around a bit and was only able to find one possible solution (and it's not even very robust): Samba supports file extension blacklisting. You should know, however, that any file with any arbitrary contents may be renamed to contain any file extension, to easily bypass file extension checks. File extension checks are useful to prevent users from accidentally activating an executable file (for example; if you have an executable file uploaded as .txt, it will harmlessly open in the user's text editor, with the worst possible consequence of freezing the text editor because the file is too large; whereas, if they upload it with the extension .exe, a double-click on Windows would run the file).

But file extension checks alone can't make sure that the CONTENTS of the file are of a desired type (or not of an undesired type). For that, you'd need some kind of hook to call custom code "upon file upload", e.g. in an FTP server (I'm not aware of any FTP servers that can be extended this way, off the top of my head) -- and then call, e.g., the UNIX utility file on the results to see if it's of an undesired type. file is not bulletproof, but it's very good at recognizing the contents of a file, irrespective of its name.


Last thing I'll leave you with to muse over: The problem of disallowing undesired file contents is much larger if you look beyond the surface. For example, assume you start out with a PDF document. Now, flip one bit in that PDF document so that the file's format now violates the PDF standard. If you open this file in a "naive" PDF reader, it would fail to open due to the file format being violated. However, if you open it in a "smart" PDF reader, it may be able to automatically detect and repair the corruption! Your file type detection program may be fooled into thinking it's not even a PDF document, if the corruption is severe enough. But an end-user might still be able to open the file.

Worse still, if you are trying to suppress specific file contents or file types from being transmitted, there are unlimited numbers of ways for users to bypass this. One approach would be to deliberately corrupt the file header beyond recognition, so that your blacklist doesn't understand the file type, thus allowing it through by default; or, if you have a whitelist, to disguise the file as a valid file format of an allowed type, but then have the contents contain the actual payload. A cooperating pair of users (or an attacker with remote control over another user) could upload and then download this file, change the contents on the receiving end to the desired format, and use the data.

This gets into the field of steganography, where you use extinct stegosaurus DNA to try and determine whether a file is of a given type ;-) (just kidding; stegosauri have nothing to do with steganography :)). In steganography, a file could appear perfectly legitimate on the surface, and even be allowed by a whitelist filter; but the attacker could cooperate with another user to communicate arbitrary data (in any file format) by hiding it within the seemingly-valid data of an existing file. Steganography can be incredibly hard to detect.

However, if your intent is just to block "happy path" file types, where the file openly and blatantly declares itself of a particular type, you can use something like file on files in a staging directory that you allow uploads to over FTP, and then, if the file "checks out" based on your test, you can move it over to the restricted directory. This will work perfectly for preventing users, who are not trained in cryptography/steganography, from uploading undesired file types to your system.

share|improve this answer
    
Brilliant answer. I'll look into it a bit more. Thanks for your input on this! –  Monty Jul 14 at 15:02
    
It is also possible to build a "write only" directory whose contents cannot be listed, but files created in. –  Simon Richter Jul 14 at 15:18
    
How would a write-only directory prevent users from writing undesired content/file types to that directory? ... Well, I suppose you could use a write-only directory as part of your solution: have users "drop" their (unverified; could be malicious or undesired content) files into the write-only directory, and then use your fanotify or inotify based program to process those files one at a time, and if they look good, mv them over to the directory where only the "known-good" files go, and the end-user program (web server or whatever) picks them up and processes them. –  ÃŁŁǫǛȉЖΦΤїҪ Jul 14 at 15:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.