在MVC3中检查上传文件是否有病毒

11

在存储文件之前,如何检查上传的文件是否存在病毒?

我之前读过这个话题,但如何以编程方式实现并向用户返回结果?

避免任何类型的用户上传文件问题的最佳方法是,在服务器上安装命令行病毒扫描程序,在上传后使用它来扫描文件。如果扫描结果是阳性的,则删除该文件等。


嗨,我想知道你是如何让这个工作的,以及你发现哪种解决方案最好用? - Dai Bok
1
你可以使用IAttachmentExecute API。这个答案可以帮助你 - Fred
你可以使用IAttachmentExecute API。这个答案可以帮助你 - Fred
5个回答

8
请查看 Sophos API:https://secure.sophos.com/partners/oem/integration/savdi.html “SAV动态接口(SAVDI)为Sophos检测引擎提供了易于集成的通用接口。它使任何语言编写的程序能够扫描恶意软件文件和数据,尤其受到在.NET环境下运行的ISP/ASP的欢迎。”
另一种选择是使用 Process 类在服务器上启动反病毒扫描程序 (http://www.dotnetperls.com/process-start) 并解析其结果。例如,以下是 AVG 的命令行参数列表:http://www.avg.com/ww-en/faq.num-3604
顺便说一下,当您开发解决方案时,您需要测试是否能够识别感染的文件。但不建议使用真正的感染文件。但是,您可以创建一个包含以下字符串的文本文件。这个字符串通常被反病毒扫描程序识别为测试目的而准备的感染文件(有关更多信息,请搜索 EICAR 标准反病毒测试文件)。
*X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H**

3

为了让您的生活更轻松……请查看Metascan Online。他们提供一个在线免费公共API。将来,您还可以通过Metascan Online公共API设置以编程方式执行此操作的方法。

    Sample Code(PHP)

       // Config.
        $api    = 'https://api.metascan-online.com/v1/file';
        $apikey = 'E1D7-DG5E-4FE0-BFAE';
        $file   = 'test.txt';

      // Build headers array.
      $headers = array(
  'apikey: '.$apikey,
  'filename: '.basename($file)
      );

      // Build options array.
      $options = array(
  CURLOPT_URL       => $api,
  CURLOPT_HTTPHEADER    => $headers,
  CURLOPT_POST      => true,
  CURLOPT_POSTFIELDS    => file_get_contents($file),
  CURLOPT_RETURNTRANSFER    => true,
  CURLOPT_SSL_VERIFYPEER    => false
      );

      // Init & execute API call.
      $ch = curl_init();
      curl_setopt_array($ch, $options);
      $response = json_decode(curl_exec($ch), true);

      print_r($response);

这是你想要使用的引擎,如果你严肃对待多重扫描的话。他们还使用超过40个引擎来扫描文件。

2

我对此主题进行了一些研究,以下是摘要。(主要针对Windows和C#,因为我使用的是Windows操作系统,并且我们正在使用Symantec防病毒软件)

  1. Symantec产品:

    a. Systemtec扫描引擎: 它类似于一个私有的反病毒服务,并提供SDK以集成到您的系统中。

    b. Doscan.exe: 这是一个命令行工具,我可以在我们公司的系统中找到。我们可以通过创建新进程来在代码中使用它来扫描文件。它使用Symantec扫描器相同的扫描过程。因此,在软件执行长时间扫描时会被阻止。

  2. 反病毒扫描程序

    这个库是反病毒软件产品(如“Microsoft Security Essentials (Windows Defender)”)的包装器,它安装在您的Windows操作系统上。由于我无法停止我的机器上Symantec的实时扫描,所以不知道它是否有效。我发现有用户说它不起作用,但我没有检查。

  3. Windows Defender :

    它是内置于Windows系统中的反病毒软件。据说它有一个命令行工具(mpcmdrun.exe),但我在我的机器上找不到它。由于我们正在使用Symantec,它被禁用了。如果您有它,可以试试。

  4. 开源反病毒产品

    ClamAV是一个流行的开源反病毒产品。一些产品将其集成到他们的系统中。它还有C# API,因此也可以用来制作私有云扫描引擎。

  5. 商业扫描引擎开放API,例如: Virustotal和Sophos。


2

尝试使用像virusTotal或类似的在线资源进行扫描。 另外我知道卡巴斯基有一个在线扫描器,但目前不可用。

从应用程序角度来看,您可以创建代理服务器,在此服务器上安装防病毒软件,将文件上传到该服务器上,进行扫描并传输到目标服务器。


1
如果您这样做,请务必检查网站的服务条款,很可能他们不允许这样的使用(至少不是免费的,他们可能有一项商业服务可供付费使用)。 - Scott Chamberlain
这是一个不错的选择,但由于文件需要几个小时扫描,所以在网站提交表单中效果较差... - Serj Sagan

2
我在寻找解决一个非常相似的问题,并没有在内存扫描方面找到很多信息。我发现的大多数示例都涉及将文件写入磁盘,然后通过将一些变量传递给另一个进程来扫描磁盘上的文件。
因此,在我使用的解决方案中,我只是使用HttpPostedFileBase.InputStream,并将其发送到ClamAv进行扫描。 在MVC中,几乎没有代码可以让它工作,非常简单。
因此,在您的MVC控制器中,您将拥有这样的内容:
/// 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);
    }
}

翻译:VirusScannerFactory的实现可以扩展以适应您的防病毒厂商。
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);
}

我以nClam和ClamAv为例。完整的ClamAv实现可以在github上找到,但是如何让它适用于内存流的代码片段如下:
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;
    }
}

我创建了一篇 博客文章,详细介绍了如何使用 ClamAv 进行此操作。

3
请避免回答主要是其他网站的链接,因为如果URL移动/失效等,它们会变得不太有用。您能否将您博客中的一些相关摘录编辑到您的答案中? - Michael Edenfield

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接