如何阻止人们上传带有注射剂的GIF?

我有一个PHP网站,人们可以在其中填写帮助票证。它允许他们上传门票的屏幕截图。我允许上传gif,psd,bmp,jpg,png,tif。收到上传后,PHP 脚本将忽略文件扩展名。它仅使用 MIME 信息标识文件类型,对于这些文件类型,MIME 信息始终存储在文件的前 12 个字节中。

有人上传了几个GIF,当使用浏览器查看时,浏览器说它是无效的,我的病毒扫描程序提醒我这是注射(或类似的东西)。有关包含这些 GIF 的 zip 文件,请参见下文。

我不认为只检查标题信息就足够了。我听说图像可以完全有效,但也包含漏洞利用代码。

所以我有两个基本问题:

  1. 有谁知道他们是如何将坏东西注入GIF的(同时仍然保持有效的GIF MIME类型)?如果我知道这一点,也许我可以在上传时检查它。
  2. 如何防止他人上传此类文件?
    • 我正在使用共享主机,因此无法安装服务器端病毒扫描程序。
    • 将信息提交到在线病毒扫描网站可能太慢。
    • 有没有办法使用PHP类来检查我自己,以检查这些东西?
    • 如果 GD 图像无效,使用 GD 调整图像大小会失败吗?或者,该漏洞是否仍会滑过并位于调整大小的映像中?如果它失败了,那将是理想的,因为这样我就可以使用调整大小作为一种技术来查看它们是否有效。

更新:大家,感谢您到目前为止的回复。我正在尝试在服务器上查找已上传的GIF。如果我找到它们,我会更新这篇文章。

更新 2:我为任何感兴趣的人找到了GIF。我把它们放在一个用密码“123”加密的zip文件中。它位于此处(请注意,此托管网站上有多个“下载”按钮 - 其中一些用于广告)http://www.filedropper.com/badgifs。名为5060.gif的那个被我的防病毒软件标记为特洛伊木马(TR / Graftor.Q.2)。我应该注意,这些文件是在我实现前12个字节的MIME检查之前上传的。所以现在,我对这些特定的是安全的。但我仍然想知道如何检测隐藏在正确MIME类型后面的漏洞利用。


重要说明:我只关心下载这些文件以查看它们的PC的风险。这些文件不会对我的服务器造成风险。他们不会被执行。它们使用扩展名为“.enc”的干净名称(十六进制哈希输出)存储,我使用fwrite过滤器将它们以加密状态保存到磁盘:

// Generate random key to encrypt this file.
$AsciiKey = '';
for($i = 0; $i < 20; $i++)
    $AsciiKey .= chr(mt_rand(1, 255));

// The proper key size for the encryption mode we're using is 256-bits (32-bytes).
// That's what "mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)" says.
// So we'll hash our key using SHA-256 and pass TRUE to the 2nd parameter, so we
// get raw binary output.  That will be the perfect length for the key.
$BinKey = hash('SHA256', '~~'.TIME_NOW.'~~'.$AsciiKey.'~~', true);

// Create Initialization Vector with block size of 128 bits (AES compliant) and CBC mode
$InitVec = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
$Args = array('iv' => $InitVec, 'key' => $BinKey, 'mode' => 'cbc');

// Save encoded file in uploads_tmp directory.
$hDest = fopen(UPLOADS_DIR_TMP.'/'.$Hash.'.enc', 'w');
stream_filter_append($hDest, 'mcrypt.rijndael-128', STREAM_FILTER_WRITE, $Args);
fwrite($hDest, $Data);
fclose($hDest);

答案 1

至于第一个问题,你永远不会真正知道你是否能够检索任何日志或有问题的图像,因为这些漏洞利用可能针对很多事情,并且根据目标是什么,漏洞利用被放入文件的方式可能完全不同。

编辑:W32 / Graftor是似乎具有类似特洛伊木马特征的程序的通用名称

在十六进制编辑器中打开文件后,我注意到该程序实际上是一个重命名的Windows程序。虽然它不是浏览器漏洞,因此除非它实际打开和执行,否则是无害的,但您必须确保它没有使用上传者定义的MIME类型,因为用户可能仍然被欺骗打开程序;请参阅第二个问题的答案。5060.gif

至于第二个问题:为了防止任何漏洞利用代码被运行或用户,你必须确保所有文件都以安全扩展名存储在文件名中,以便它们以正确的MIME类型提供。例如,您可以使用此正则表达式来检查文件名:

if(!preg_match ( '/\\.(gif|p(sd|ng)|tiff?|jpg)$/' , $fileName)){
    header("415 Unsupported Media Type");
    die("File type not allowed.");
}

还要确保您提供的文件具有正确的内容类型;确保在向用户提供文件时不使用与上载文件一起指定的内容类型。如果您依赖于上传者指定的内容类型,则该文件可能会作为或类似内容提供,并将由用户的浏览器进行解析。text/html

请注意,这只能防止恶意文件利用用户浏览器中的漏洞,图像解析器除外。

如果您试图防止针对服务器的漏洞利用,则必须确保不会让PHP解析器执行图像的内容,并且您用于处理图像的图像库没有任何已知的漏洞。

另请注意,此代码不会保护您免受包含用户浏览器使用的图像解析器的漏洞的图像的攻击;为了防止这种情况,您可以检查是否按照Jeroen的建议评估为真。getimagesize()

请注意,如果您不检查文件名并确保文件具有正确的标头,则仅使用是不够的,因为完全有效的图像可以在注释中嵌入HTML / PHP代码。getimagesize()Content-Type


答案 2

您可以使用 getimagesize() 函数来实现此目的。如果图像无效,它将简单地返回 。false

if (getimagesize($filename)) {
    // valid image
} else {
    // not a valid image
}

值得注意的是,这也不是100%安全的,但据我所知,这是你能做的最好的事情。

在此处阅读有关此内容的更多信息


推荐