What are my options to check for viruses on a PHP upload?
ClamAV is a free anti virus commonly used on server applications.
php-clamav is an extension for binding ClamAV to PHP. You can check their documentation.
I've found a tutorial on how to use clamav as a Zend Framework Validator which already includes instructions on how to verify upload files. The tutorial should also help you on using it on another frameworks or architectures.
You can also call clamav by its command line interface with clamscan
. This requires clamav to be installed but not the PHP extension. In the PHP side, you can shell_exec('clamscan myuploadedfile.zip');
then parse the output. Lines ending with OK
are safe files, lines ending with FOUND
are malicious files.
Scan PHP uploads for viruses
If you don't need to display the results to the user instantly, you could add the file to a Database table for scanning later.
Then, you could fork a new process to scan and update the results in the table. You have a good example here: http://robert.accettura.com/blog/2006/09/14/asynchronous-processing-with-php/.
If you absolutely need to display the results within the same request, then you could do it exactly as I said before but outputting a temp page requesting the results via AJAX; once the scan is over, redirect the user to the results page.
If you don't want to use JavaScript, then a simple meta refresh tag would do the trick.
Antivirus scan for uploading files
I found a list on antivirus software for ubuntu, and they should be LSD compatible, so they should work on Centos. You can use the link above the check if they are.
The list is here, and wikipedia also contains a list of linux antiviruses.
I am not sure if they all suit your needs, but I know that AVIRA has a command line scanner.
Here are some sample lines of code:
scancl / --defaultaction=ask
scancl /var/www -z --defaultaction=repair,delete
Validate an uploaded file for size and viruses
The maximum file size is being checked by PHP when it decodes the POST request. It's set in the php.ini with
- File size check before saving it to server. (Checking file size while it is being uploaded)
upload_max_filesize
. It's usually around 10MB or so.But you can easily set your application specific maximum filesize with a simple test:
if ($_FILES["image"]["size"] >= 500000) {
Then react accordingly and print an error message. 500K should be more than enough for profile images and avatars.You will need to install a virus scanner on the server then. There are various available. Since it is open source, many Unix/Linux servers might have clamav. It can be utilized like this from PHP:
- Scan file contents
exec("clamscan '$filename'", $output, $result);
if ($result === 0) {
// everything ok
}
The output status $result
would be 1
for a virus or 2
for other errors. antivirus check on PHP image upload necessary or not?
Why using an antivirus could be useful:
It is technically possible for an image to exploit a vulnerability in a system, not just as metadata, but in different ways, depending on the software that opens the image.
For instance, one of the first PSP vulnerabilities was due to the way the image viewer parsed a TIFF image (http://www.makeuseof.com/tag/how-to-downgrade-your-psp-and-upgrade-to-a-custom-firmware-part-one/#2.00).
Although probably unlikely, there could be a bug/vulnerability/backdoor in the library that resizes the image, so if you want to go the extremely cautious route, the order would be:
- Hand the image to the antivirus
- Process/store the image in any way.
NB: Having your library packages kept up to date goes a longer way than an AV, since after modification of the original image, any vulnerability exploitation will be probably corrupted/lost.
Related Topics
Converting JSON to CSV Format Using PHP
Php: $_Server Variables: $_Server['Http_Host'] VS $_Server['Server_Name']
How to Access Elements in an Array Returned from a Function
Best Way to Get Hostname with PHP
Difference Between Buffered and Unbuffered Queries
Disable Doctrine 2 Lazy Loading When Using Jms Serializer
What Is the Js Equivalent to the PHP Function Number_Format
How Would You Transform a Pre-Existing Web App into a Multilingual One
How to Use Laravel Passport with a Custom Username Column
File_Get_Contents('Php://Input') Always Returns an Empty String
Doctrine2 Findby Relationship Object Triggers String Conversion Error
Cannot Set Date.Timezone in PHP.Ini File
How to Select Year and Month from the Created_At Attributes of Database Table in Laravel 5.1
Make Script Execution to Unlimited