Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check upload file for virus in MVC3

How can i check upload file for virus before store it?

I previously read this topic,but how can i do it programmatic and return result for user?

The best way to avoid problems with user uploaded files of any kind is to have a command line virus scanner on the server, which you use to scan the files after upload. If the scanner result is positive, delete the file and so on

like image 347
KF2 Avatar asked Jul 20 '13 17:07

KF2


2 Answers

I was looking to solve a very similar problem, and did not find much on in memory scanning. Most examples I found involve writing the file to disk, and then scanning by passing some variables to another process to scan the file on disk.

So in the solution I have used I just use the HttpPostedFileBase.InputStream, and send that to ClamAv to scan. There is not much code to get it working in MVC and its QED.

So in your MVC controller, you'll have something like this:

/// Main controller
public class HomeController : Controller {

    /// Get the upload view
    [HttpGet]
    public ActionResult Index() {
        return View();
    }

    /// Handle the file upload
    [HttpPost]
    public ActionResult Index(UploadViewModel model, HttpPostedFileBase file) {
        var scanner = VirusScannerFactory.GetVirusScanner();
        var result = scanner.ScanStream(file.InputStream);

        if(result.IsVirusFree) {
            // save to disk
        } else {
            // don't save to disk and tell user they uploaded a virus
        }

        return View(model);
    }
}

The Implementation of the VirusScannerFactory can be extended to suite your AV vendor.

public class VirusScannerFactory {
    public static IScanViruses GetVirusScanner() {
        //Currently we only have one Antivirus implementation, 
        //but later we want to include AVG, SOPHOS and metascan 
        return new ClamAvScanner();
    }
}

public interface IScanViruses {

    ScanResult ScanFile(string fullPath);

    ScanResult ScanBytes(byte[] bytes);

    ScanResult ScanStream(Stream stream);
}

I have used nClam and ClamAv as an example. The full ClamAv implementation can be found on github, but a snippet of how you get it working for memory streams is below

public class ClamAvScanner : IScanViruses{
    ... snip ...
    /// Scans your data stream for virus
    public ScanResult ScanStream(Stream stream) {
        var clam = new ClamClient("localhost", 3310);
        return MapScanResult(clam.SendAndScanFile(stream));
    }
    ...snip ...
    /// helper method to map scan result
    private ScanResult MapScanResult(ClamScanResult scanResult) {
        var result = new ScanResult();
        switch (scanResult.Result) {
            case ClamScanResults.Unknown:
                result.Message = "Could not scan file";
                result.IsVirusFree = false;
            break;
            case ClamScanResults.Clean:
                result.Message = "No Virus found";
                result.IsVirusFree = true;
                break;
            case ClamScanResults.VirusDetected:
                result.Message = "Virus found: " + scanResult.InfectedFiles.First().VirusName;
                result.IsVirusFree = false;
                break;
            case ClamScanResults.Error:
                result.Message = string.Format("VIRUS SCAN ERROR! {0}", scanResult.RawResult);
                result.IsVirusFree = false;
                break;
           }
        return result;
    }
}

I created a blog post with full details of how to do this with ClamAv.

like image 51
Dai Bok Avatar answered Oct 23 '22 23:10

Dai Bok


Take a look at Sophos API https://secure.sophos.com/partners/oem/integration/savdi.html

"SAV Dynamic Interface (SAVDI) provides an easy-to-integrate, general-purpose interface to the Sophos detection engine. It enables programs written in any language to scan files and data for malware and is particularly popular with ISPs/ASPs running in a .NET environment."

Another alternative is to use Process class to start an anti-virus scanner on the server (http://www.dotnetperls.com/process-start) and parse its results. For example, here's the list of command-line parameters for AVG: http://www.avg.com/ww-en/faq.num-3604.

By the way, as you develop your solution, you will need to test if you're able to identify an infected file. But it's not recommended to use a real infected file. However, you can create a text file with the string below. This string is commonly identified by anti-virus scanners as a infected file for testing purposes (for more information, search for EICAR Standard Anti-Virus Test File).

*X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H**

like image 21
Fabio Avatar answered Oct 23 '22 23:10

Fabio