Secure File Upload in PHP: A Guide
Writing a script letting us upload files might be relatively easy, but the security of such an approach is a different beast altogether – this is what we explore in this blog.
Why Build File Uploading Functions in PHP?
File uploading functions are a necessity for many applications that let users interact with other users in a commercial fashion: think of businesses running classifieds sites, for example. Many of such enterprises encompass a couple of business lines – some of them deal with real estate, automobiles, employment, and general classifieds sites. For many such businesses, file uploading functions are an absolute necessity to drive revenue – users must upload text, images, and descriptions of a certain product.
The security of file upload functions is an absolute must for every business – it’s easy for such a feature to slip out of hands, and as it’s sometimes built while neglecting basic concepts, the consequences for some businesses are terrific – when exploiting improperly built functions, hackers upload malicious files, implement backdoors, deface websites, and sometimes cause a lot of downtime. There’s an easy way to prevent all of this from happening – we need to secure all of our forms that let people upload files onto any server.
How to Make Our Uploads Secure?
To protect our applications from the aforementioned threats, we need to ensure that:
- Our file upload forms only accept a predefined set of extensions (e.g. if our application is supposed to let users upload images, we need to ensure that the form only accepts files having the jpg, jpeg, gif, or png extensions.)
- We prevent the uploading of files having two file types (e.g. .jpg.png, etc.)
- We avoid uploading files to the root directory and have them uploaded to a subdirectory instead.
These three points will take care of three crucial problems:
- If a file with a server-executable extension (for example .php) is uploaded, the form will turn it down.
- If anyone uploads a file with two file extensions like .php.png, they are assuming that our script only checks if the image is of the “png” file type ignoring all other extensions – that won’t be the case, so such a scenario will be avoided.
- By placing all uploaded files inside of a subdirectory, we take care of another crucial problem – should a problematic file be still uploaded and all of our restrictions bypassed, at least it will be uploaded into a directory that could prevent server-sided scripts from executing entirely (that can be done via .htaccess) and in some cases won’t be easily accessible.
To add to the last point, we should consider disabling PHP from running inside of the folder that uploaded files reside in entirely for maximum security – simply add this code snippet inside of your .htaccess file to achieve that:
Image 1 – .htaccess code to prevent the execution of PHP files
Once that‘s done, we should build our PHP file-uploading script. Here‘s a basic form of such an approach:
- We should look up how to build a basic file uploading function in PHP. Here‘s a basic script that does just that (do note that there is no protection from any aforementioned issues):
- We should ensure that we have a safe and secure place to save all uploads in.
- We should check the MIME file type of the uploaded file.
- We should consider renaming the uploaded file after ensuring that its extension is in a list of allowed extensions.
- We should consider saving the name of the file and its MIME type in our database.
Follow the outlined steps together with the advice outlined above, and you should be good to go.
Handing uploaded files on the server side when using PHP might not be the simplest of tasks, however, it can be done once we have some security knowledge in this space. We hope that this blog has been helpful and you will consider staying around the BreachDirectory space for more content – make sure to run a search through the search engine and consider implementing the API offering into your infrastructure to secure both yourself and your employees, and until next time.