PHP EXIF进程IFD标记远程整数溢出
背景: 我一直在研究一个问题,即文件上传表单只接受特定的图像,这不是图像大小(维度)或大小(文件大小)的问题,但我认为我发现这与图像位深度有关,因为PHP脚本调整图像大小并应用静态(半透明)将水印文件添加到图像并保存结果 我今天和昨天都经历了一个漫长的过程,因为出现的错误是服务器声明“由服务器重置连接”。我想我已经缩小到服务器没有足够的空闲内存来完成图像资源操作 问题: 然后,在所有这些之后,在提交文件上载时会出现以下错误: 检测到“WEB PHP EXIF进程IFD标记远程整数溢出-2(CVE-20/缓冲区溢出)”的IP 一些谷歌搜索只告诉我,这是PHP<4.2的安全漏洞,与实际情况无关 我已经看过我的代码,并且非常确定 我的问题是试图阐明这个错误语句的含义(以及我如何着手纠正它) 注意事项:PHP EXIF进程IFD标记远程整数溢出,php,apache,exif,integer-overflow,Php,Apache,Exif,Integer Overflow,背景: 我一直在研究一个问题,即文件上传表单只接受特定的图像,这不是图像大小(维度)或大小(文件大小)的问题,但我认为我发现这与图像位深度有关,因为PHP脚本调整图像大小并应用静态(半透明)将水印文件添加到图像并保存结果 我今天和昨天都经历了一个漫长的过程,因为出现的错误是服务器声明“由服务器重置连接”。我想我已经缩小到服务器没有足够的空闲内存来完成图像资源操作 问题: 然后,在所有这些之后,在提交文件上载时会出现以下错误: 检测到“WEB PHP EXIF进程IFD标记远程整数溢出-2(CVE
- PHP 5.6.16
- 页面上没有运行PHP EXIF函数
- 我在页面上看不到任何会导致整数溢出的地方(我想是无限大)
- 页面确实使用了
、imagecopy
和imagealphabling
,但此错误通知似乎出现在脚本在上载文件上运行之前imagesavealpha
- 此错误仅发生在某些上载的图像上,而不发生在其他图像上
- 我没有发现与此相关的Apache错误日志
- 我没有记录PHP错误
听起来你有一个转发IP,它阻止上传可能会出错的图像。@bishop非常感谢这个链接。我在理解布局/信息方面有点困难。从错误报告的详细信息来看,它已经关闭了,所以我认为如果我下载并用ext/ex替换服务器版本exif,我的想法是否正确如果/exif.c
链接到bug修复程序,那么应该对其进行排序。很抱歉,可能是一个明显的问题:-/我认为升级PHP不会修复此错误,原因有两个。首先,此错误字符串不存在于5.6版的PHP exif扩展源代码中,这表明您正在使用。其次,错误字符串包含字符串“IPS”,这向我强烈建议,有一个入侵保护系统硬件/软件组件正在PHP获取图像之前扫描EXIF。@bishop谢谢,我想我是充满希望的!我已经看过WHM,但没有看到相应的防火墙程序的迹象(因此我猜它可能超出了WHM的范围)乐观一点也没有坏处!请发布您正在使用的托管提供商和服务器操作系统。这可能有助于确定源代码。听起来您有一个转发IP,阻止上传可能会出错的图像。@bishop非常感谢看起来像这样的链接。我在理解布局/信息方面有点困难。由于错误报告详细信息,它已关闭,因此如果我下载服务器版本exif并将其替换为从错误修复程序链接的ext/exif/exif.c
,那么我的想法是否正确,应该对其进行排序。很抱歉,可能是一个明显的问题:-/我认为升级PHP不会修复此错误,原因有两个。首先,此错误字符串不存在于PHP exif ex中表示正在使用的版本5.6的源代码。其次,错误字符串包含字符串“IPS”,这向我强烈建议,有一个入侵保护系统硬件/软件组件正在PHP获取图像之前扫描EXIF。@bishop谢谢,我想我是充满希望的!我已经看过WHM,但没有看到相应的防火墙程序的迹象(因此我猜它可能超出了WHM的范围)乐观一点也没有坏处!请发布您正在使用的主机提供商和服务器操作系统。这可能有助于确定源代码。
<?php
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
///first set out variables.
$goodImage = 0;
$maxfilesize = (int)$_POST['MAX_FILE_SIZE'];
$gallery = (int)$_POST['galfolderid']
if (empty($gallery)) {
$_SESSION['message'] = $gallery . "<br/>Gallery Value has not been set.";
}
elseif (!is_numeric($gallery)) {
$_SESSION['message'] = $gallery . "<br/>Gallery Value is not a numeric value.";
}
elseif (!is_dir($_SERVER['DOCUMENT_ROOT']."/images/gallery/" . $gallery )) {
$_SESSION['message'] = $gallery . "<br/>Gallery Value, while being a number, is not a valid numeric value.";
}
if(!empty($_SESSION['message'])) {
header("Location:editgallery.php?gallery=".$galleryid);
exit;
}
for($count=0;$count<5;$count++) {
if ($_FILES['image']['error'][$count] == 0) {
clearstatcache();
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$imageType = finfo_file($finfo, $_FILES['image']['tmp_name'][$count]);
finfo_close($finfo);
unset($finfo);
if (strtolower($imageType) == "image/png") {
$imgtype = "PNG";
$original = imagecreatefrompng($_FILES['image']['tmp_name'][$count]);
} elseif (strtolower($imageType) == "image/jpeg" || strtolower($imageType) == "image/jpg") {
$imgtype = "JPG";
$original = imagecreatefromjpeg($_FILES['image']['tmp_name'][$count]);
} else {
//not a JPG or PNG type... set error.
$_SESSION['message'] = "Image " . ($count+1) . " does not appear to be a valid .JPG or .PNG file. ";
error_log($_SESSION['message']);
header("Location:editgallery.php");
exit;
}
unlink($_FILES['image']['tmp_name'][$count]);
$edgePadding = (int)$_POST['WMedge'][$count]; //integer
$watermarkScale = $_POST['WMscale'][$count]; //float
$h_position = $_POST['Hpos'][$count]; //text array
$v_position = $_POST['Vpos'][$count]; //text array
$Hoz = $h_position[0];
$Vez = $v_position[0];
if (!isset($watermarkScale) || empty($watermarkScale) || !is_numeric($watermarkScale)) {
$watermarkScale = 1.0;
}
elseif($watermarkScale > 2.0) {
$watermarkScale = 2.0;
}
elseif($watermarkScale < 0.5) {
$watermarkScale = 0.5;
}
if ((!isset($edgePadding) || empty($edgePadding) || !is_numeric($edgePadding)) && $edgePadding !== "0") {
$edgePadding = 5;
}
// be sure that the other options we need have some kind of value
if ($_FILES['image']['size'][$count] > $maxfilesize) {
$_SESSION['message'] .= "Image file ".($count+1)." appears to be too big. There is a limit of 2Mb on the
size of the image you can upload. Please click 'Back' on your browser and resubmit a valid image.";
error_log($_SESSION['message']);
//file too big.
}
//target name is the number of images in the LARGE gallery,
///cycle through imagenames to find the first "clear" image number.
$newimagename = 1;
clearstatcache();
/***
NOTE: Only possible place an integer oveflow might occur I think
***/
while (file_exists($_SERVER['DOCUMENT_ROOT'] . "/images/gallery/" . $gallery . "/S/" . $newimagename . ".jpg")) {
$newimagename++;
}
///newimagename is the new filename of the image.
$target_name = $newimagename . ".jpg";
$target = $_SERVER['DOCUMENT_ROOT'] . "/images/gallery/" . $gallery . "/L/" . $target_name;
$targetSmall = $_SERVER['DOCUMENT_ROOT'] . "/images/gallery/" . $gallery . "/S/" . $target_name;
//targetSM is used below to make the thumbnail image. for the SMALL gallery.
//full target directory and name.
// file upload success
// now file need resizing before the watermark is applied.
// resize new dimensions (Large- 800px)
$originalImageSize[0] = imagesx($original);
$originalImageSize[1] = imagesy($original);
/***
* Resize new dimensions for small thumbnail.
***/
if ($originalImageSize[0] > 133) {
$percent = 133 / $originalImageSize[0];
} else {
$percent = 1;
}
$newThumbHeight = $originalImageSize[1] * $percent;
$newThumbWidth = $originalImageSize[0] * $percent;
// Resample
$imageThumbFinal = imagecreatetruecolor($newThumbWidth, $newThumbHeight);
imagecopyresampled($imageThumbFinal, $original, 0, 0, 0, 0, $newThumbWidth, $newThumbHeight, $originalImageSize[0], $originalImageSize[1]);
// Output
imagejpeg($imageThumbFinal, $targetSmall, 80);
imagedestroy($imageThumbFinal);
unset($imageThumbFinal, $percent,$newThumbWidth,$newThumbHeight);
/***
* End Thumbnail generation.
*/
/***
* Resize main sized image (max 800px wide)
***/
if ($originalImageSize[0] > 800) {
$percent = 800 / $originalImageSize[0];
} else {
$percent = 1;
}
$newPictureHeight = $originalImageSize[1] * $percent;
$newPictureWidth = $originalImageSize[0] * $percent;
// Resample main image to reduce max size.
$imageCleanFinal = imagecreatetruecolor($newPictureWidth, $newPictureHeight);
imagecopyresampled($imageCleanFinal, $original, 0, 0, 0, 0, $newPictureWidth, $newPictureHeight, $originalImageSize[0], $originalImageSize[1]);
/***
* Now resize the watermark and save onto the final image.
***/
//full target directory and name.
$watermark = $_SERVER['DOCUMENT_ROOT'] . "/images/watermark2.png";
$wmTarget = substr($watermark, 0, -3) . "tmp"; //image/watermark2.tmp is resized.
$sourceWaterImage = imagecreatefrompng($watermark);
$waterMarkWidth = imagesx($sourceWaterImage);
$waterMarkHeight = imagesy($sourceWaterImage);
$destinationHeight = $waterMarkHeight * $watermarkScale;
$destinationWidth = $waterMarkWidth * $watermarkScale;
$destinationHeight = floor($destinationHeight);
$destinationWidth = floor($destinationWidth);
$destinationWatermarkImage = imagecreatetruecolor($destinationWidth, $destinationHeight);
imagealphablending($destinationWatermarkImage, FALSE);
imagesavealpha($destinationWatermarkImage, TRUE);
imagecopyresampled($destinationWatermarkImage, $sourceWaterImage, 0, 0, 0, 0, $destinationWidth,
$destinationHeight, $waterMarkWidth, $waterMarkHeight);
imagedestroy($sourceWaterImage);
unset($sourceWaterImage);
clearstatcache();
/***
* Set watermark location on final image.
***/
$differenceX = $newPictureWidth - $destinationWidth;
$differenceY = $newPictureHeight - $destinationHeight;
switch ($Hoz) {
// find the X coord for placement
case 'left':
$placementX = $edgePadding;
break;
case 'center':
$placementX = round($differenceX / 2);
break;
case 'right':
$placementX = $newPictureWidth - ($destinationWidth + $edgePadding);
break;
default:
$placementX = 0;
break;
}
switch ($Vez) {
// find the Y coord for placement
case 'top':
$placementY = $edgePadding;
break;
case 'middle':
$placementY = round($differenceY / 2);
break;
case 'bottom':
$placementY = $newPictureHeight - ($destinationHeight + $edgePadding);
break;
default:
$placementY = 0;
break;
}
/***
* Finish set Watermark location
***/
imagecopy($imageCleanFinal,
$destinationWatermarkImage,
$placementX,
$placementY,
0,
0,
$destinationWidth,
$destinationHeight);
imagejpeg($imageCleanFinal, $target, 80);
/***
* Image final save
***/
// Output
imagejpeg($imageCleanFinal, $target, 80);
imagedestroy($imageCleanFinal);
imagedestroy($destinationWatermarkImage);
unset($imageCleanFinal, $percent);
unlink($wmTarget);
$output[$goodImage]['targetName'] = $target_name;
$output[$goodImage]['targetAddr'] = $target;
$goodImage++;
} elseif (!isset($_FILES['image']['name'][$count]) || ($_FILES['image']['error'][$count] != 0 && $_FILES['image']['error'][$count] != 4)) {
//error in file upload.
$_SESSION['message'] .= " There is a file upload error number " . $_FILES['image']['error'][$count] . ". for image ".($count+1).".
Please try resubmitting a valid image.";
error_log($_SESSION['message']);
}
}
if (empty($_SESSION['message'])){
$_SESSION['message'] = $goodImage." New Image(s) Uploaded";
}
// display resulting image for download
header("Location:editgallery.php?special=yes&gallery=".$galleryid);
exit;