php - 有什么方法可以阻止人们上传带有注入(inject)的 GIF 动图?

标签 php security image-processing gd code-injection

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

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

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

所以我有两个基本问题:

  1. 有谁知道他们是如何将不良内容注入(inject) GIF 的(同时仍保持有效的 GIF MIME 类型)?如果我知道这一点,也许我可以在上传时进行检查。
  2. 如何防止有人上传这样的文件?
    • 我在共享主机上,所以我无法安装服务器端病毒 扫描仪。
    • 将信息提交到在线病毒扫描网站 可能太慢了。
    • 有没有什么方法可以使用检查这些东西的 PHP 类来检查我自己?
    • 如果无效,使用 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);

最佳答案

至于第一个问题,您永远不会真正知道您是否无法检索任何有问题的日志或图像,因为这些漏洞利用可能针对很多事情并依赖于将漏洞放入文件的方式可能完全不同。

编辑: W32/Graftorgeneric name适用于看似具有木马特征的程序。

在十六进制编辑器中打开文件 5060.gif 后,我注意到程序实际上是一个 renamed windows program .虽然它不是浏览器漏洞,因此除非它被实际打开并执行,否则它是无害的,但你必须确保它不是由上传者定义的 MIME 类型提供的,因为用户仍然可能被欺骗打开程序;看第二个问题的答案。

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

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

还要确保您使用正确的内容类型提供文件;确保在向用户提供文件时不使用上载文件指定的内容类型。如果您依赖上传者指定的 Content-Type,则该文件可能会以 text/html 或类似的形式提供,并将由用户的浏览器进行解析。

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

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

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

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

关于php - 有什么方法可以阻止人们上传带有注入(inject)的 GIF 动图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10865202/

相关文章:

php - 多行字符串到数组

php - 在 CodeIgniter 中选择 AVG

php - PDO 只获取单行

azure - Azure Pipelines 中存在安全漏洞?

安卓在哪里保存个人数据?

python - 将存储为 numpy 数组的图像转换为 hsv 的有效方法

java - 拉普拉斯金字塔产生奇怪的结果?

PHP SQLite3 - 绑定(bind)值

image - 检测图像中的乐高底板

security - 保护 Web 服务器免受 Safari 中的 MITM 攻击