Making a Blacklist of filetypes to protect PHP application
It is not clear from your description why you want block these files exactly. I see the following possibilities:
- You want to block files that might infect the server itself. Unfortunately this can be about anything: shell, perl, python, awk, ... and of course compiled binaries. But to get these files executed without explicitly calling them with an interpreter the executable bit must be set, which should not be the case if the file gets uploaded from inside a web application. This is at least the case on UNIX systems, because on Windows the extension is enough and there you have also PoweShell, JavaScript, Batch and all the other files. Still, something must at least trigger the execution of the file or have the upload directory in the path for DLL's and shared libraries.
- Or you want to block files which might be executed by the web server itself, i.e. from inside the web application. These are PHP, ASP, CGI ... files which will be executed via a URL and cause harm for the user or for the server. Of course the only works if your upload directory is reachable by a URL or if the attacker manages to break out of the upload directory with path traversal attacks or similar or if the attacker manages some server side code to include these files (i.e. local file inclusion attack).
- Or you want to block files which might be included to serve malware to the user, i.e. corrupt PDF documents, javascript redirecting to malware sites. In this case you have probably a upload directory which is reachable by a URL because you want users to download these files. Unfortunately for such files not only the file type you see is important but also the context in which they are called (i.e. as image, script, css, object ...) and you are not able to control this usage.
... but in this case I need to do a blacklist of files for many reasons,
Since you obviously don't know which files can be dangerous at all such kind of blacklist will not work, ever. There will always be file types you miss or the attacker will hide its file behind some other type, i.e. construct a polyglot.
Don't block any specific MIME types. Block any kind of execution of the uploaded files. A simple way is to store uploaded files outside of the web root and serve them via scripting. If that's not possible, store files in a subdirectory and configure your server not to execute any scripts in that directory. Remember to do this for any scripting language that might possibly be enabled on the server.
If you can't modify the configuration for various reasons, check the file name, and do it properly. PHP strings can contain NULL bytes, filenames cannot, so if an attacker uploads a file called "hack.php\0.jpg", you might view the extension as ".jpg" which is valid, but it would get saved as "hack.php", making you vulnerable again. Check characters in a filename against a whitelist.
Are there any other filetype that I also should block?
It doesn't matter, as finfo_file can be bypassed, see for example here: Encoding Web Shells in PNG IDAT chunks. mime_content_type doesn't seem to be more reliable either.
You need to check for file extension in addition to the mimetype check, as it is a lot more reliable, as file names are a lot less complex than file contents.
An additional mime-type check is still a good idea as defense in depth, to filter out simple attacks. Like you said, a whitelist would be the correct approach, but if you definitely need to go with a blacklist, I would at least add PHP mimetypes to the blocklist:
- text/php
- text/x-php
- application/php
- application/x-php
- application/x-httpd-php
- application/x-httpd-php-source
Additionally, do you really need execution right in the uploads directory? If not, remove it for added security.