我有一个 PHP 网站,人们可以在其中填写帮助票。它允许他们为他们的票上传屏幕截图。我允许上传 gif、psd、bmp、jpg、png、tif。收到上传后,PHP 脚本会忽略文件扩展名。它仅使用 MIME 信息识别文件类型,对于这些文件类型,这些信息始终存储在文件的前 12 个字节中。
有人上传了几个 GIF,当用浏览器查看时,浏览器说它无效,我的病毒扫描程序提醒我这是注入(或类似的东西)。请参阅下面的包含这些 GIF 的 zip 文件。
我认为仅检查标题信息是不够的。我听说图像可以完全有效,但也包含漏洞利用代码。
所以我有两个基本问题:
- 有谁知道他们是如何将坏东西注入 GIF 的(同时仍然保持有效的 GIF MIME 类型)?如果我知道这一点,也许我可以在上传时检查它。
- 如何防止有人上传这样的文件?
- 我在共享主机上,因此无法安装服务器端病毒扫描程序。
- 将信息提交到在线病毒扫描网站可能太慢了。
- 有没有办法使用检查这些东西的 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);