As mentioned many times in this chapter, permitting users to upload files to your system exposes us to a whole new range of security problems. Fortunately, you can solve or reduce most of them with some simple precautions.
Trusted Users Only
One of the easiest things we can do to help keep our uploading system safe is to permit only registered and trusted users to perform such an action in the first place. If we allow anybody to send us files, we are exposing ourselves to all sorts of trouble with automated scripts that simply bombard our server with files, possibly causing a denial of service. (See the section "Denial of Service.")
Although requiring a successful user authentication prior to allowing uploads does not prevent a situation where a compromised user account is the source of troubles, it covers most of the problem. To prevent even compromised accounts from being problematic, we can limit the number or size of uploads they perform in any given time period (for example, 24 hours).
Denial of Service
By giving users access to our file system, we are exposing ourselves to a new type of denial-of-service attackthat of filling up our file system with large or junk files. If we have no limits on who can send us content or how often, even the size limits we set in php.ini will not protect us from hundreds of 2MB files being sent at us rapidly.
If the file system where our temporary upload directory resides is on the same file system as our PHP installation ormuch worseour core operating system files, our server could be prevented from further normal operations by being unable to create new files that it needs on a regular basis (such as temporary files or virtual memory data).
To solve this problem, create a new file system strictly for use as the temporary upload directory. The exact size depends on what the web application's needs are, but by assigning this directory its own file system (or drive letter under Windows), even if it does fill upeither by accident or intentional misusethe rest of our system remains unaffected.
As shown in the "Uploading User Files" section, when a file arrives on the server, you can take the opportunity to perform some sort of validation on it before moving it to its ultimate resting place. This validation can range from a simple filename extension verification we showed (which, it must be said, is a meager and marginally effective test) to performing binary analysis and running antivirus software on the uploaded files.
The exact needs of this step depend on your web application, what files are being uploaded, and the budget of your system. Given the chance to do some sort of validation on the data, however, it is highly worthwhile to do so.
One other attack against file uploads can come in the form of malicious users who send a request to our server claiming they uploaded a file, but without actually including content. If we, for example, take a file that a user uploads and then move it to a location where it can be viewed by others, the user might try to tell us that he sent us '/etc/ passwd' or 'C:\windows\php.ini' and not actually include a file. When we go to copy or move the file, we might accidentally expose the contents of these files or overwrite them with something else.
The code we wrote in the section "Uploading User Files" avoids this problem by using the move_uploaded_file instead of simply using rename, copy, or some other code we write ourselves. This function, along with its closely related cousin is_uploaded_file, actually makes sure that the file that was supposedly uploaded truly was. If not, it reports an error and returns FALSE. You should always use these functions when working with uploaded files.