11

Stack,

I want to scan each file that gets uploaded via my php upload script with clam anti-virus's clamscan tool. I think I've got a good script written but I wanted to run it past you guys.

So assuming that the file I'm sending to this php upload script is named "uploadedfile" does the following code make sense?

<?php

$safe_path = escapeshellarg('/tmp/' . $_FILES['uploadedfile']['tmp_name']);
$command = 'clamscan ' . $safe_path;
$out = '';
$int = -1;
exec($command, $out, $int);

if ($int == 0) {
   // all good, code goes here uploads file as normal IE move to
permanent directory etc;
} else {
   unlink('/tmp/' . $_FILES['uploadedfile']['tmp_name']);
header(Location: http://www.domain.com/uploadform.php?error=your-file-was-infected-pal);
}

?>

Also, will clamscan find php shells as well as traditional good old malware?

Thanks!

Update - found the answer

I answered my own question but don't have the reputation to officially do so. Here is the anser:

For those who come after. I've tested this script using the EICAR test virus file http://eicar.org/86-0-Intended-use.html and after a few tweaks it works. The return variable $int is what tells you whether or not the file is safe or not. If $int is 0, no virus was found, if $int is 1, a virus was found. However, there are some changes that I had to make the script work (I updated the $safe_path variable to be correct), here is the working script:

<?php

$safe_path = escapeshellarg($_FILES['uploadedfile']['tmp_name']);
$command = 'clamscan ' . $safe_path;
$out = '';
$int = -1;
exec($command, $out, $int);

if ($int == 0) {
   // all good, code goes here uploads file as normal IE move to
permanent directory etc;
} else {
  //whatever you need to do if a virus is found.
}

?>
Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
billmalarky
  • 920
  • 2
  • 12
  • 34

3 Answers3

9

Note that if your server runs a clamav daemon (clamd) it may be possible to use clamdscan instead of clamscan as proposed, this usage is faster since use virus signatures already loaded by clamd.

acesso
  • 146
  • 1
  • 4
  • 1
    This answer was a time bomb ;-) Yes that's actually what I ended up using. clamscan took like 5-6 seconds to start up, clamdscan is practically immediate. – billmalarky Apr 12 '13 at 21:48
  • Also, I have found that opening a socket connection to the clamd directly was resulting in inconsistent output (ClamAV v0.98.4 on Solaris Sparc) when recursively scanning directories. Using the clamdscan binary worked every time. – HeadCode Dec 18 '14 at 22:56
  • Thanks!! seriously helpful :) – sk8terboi87 ツ Aug 07 '16 at 12:17
  • Side note: If you use `clamd` the user that runs `clamd` needs to have permission to file that you want to scan. – Tom Raganowicz Mar 07 '18 at 12:11
1

I had a lot of trouble with permissions when trying to run this with clamdscan. I found a solution for the permissions problem here: https://wiki.archlinux.org/index.php/ClamAV

This changed this line:

$command = 'clamscan ' . $safe_path;

to:

$command = 'clamdscan  --fdpass ' . $safe_path;

Seemed to successfully pass a good file and flag an EICAR file.

Dragonthoughts
  • 2,180
  • 8
  • 25
  • 28
Chrono
  • 11
  • 1
1

Just be careful. If your clamscan becomes outdated you'll get feedback in the output:

It will look like this:

LibClamAV Warning: ***********************************************************
LibClamAV Warning: ***  This version of the ClamAV engine is outdated.     ***
LibClamAV Warning: *** DON'T PANIC! Read http://www.clamav.net/support/faq ***
LibClamAV Warning: ***********************************************************

Also depending on the version of clamscan the "result" might look like this (and you'll need to parse it accordingly):

[filename]: OK

----------- SCAN SUMMARY -----------
Known viruses: x
Engine version: x.x.x
Scanned directories: 0
Scanned files: 1
Infected files: 0
Data scanned: x.xx MB
Data read: x.xx MB (ratio 0.00:1)
Time: x.xx sec (0 m x s)
Tom
  • 3,031
  • 1
  • 25
  • 33
  • I ran the script using a normal image.jpg file and the eicar test virus file and the $int return value will return as a 0 if the file is safe and a 1 if the file is infected. So that's what I'm basing the rest of the script actions on. – billmalarky Oct 04 '11 at 15:49
  • 2
    In that case it looks good. Just remember to keep your definitions up to date. If you want to test against some shell code, just download a couple from here http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=&filter_exploit_text=&filter_author=&filter_platform=0&filter_type=4&filter_lang_id=0&filter_port=&filter_osvdb=&filter_cve= – Tom Oct 04 '11 at 20:04