php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77311 Use After Free Read through image tile and brush
Submitted: 2018-12-17 15:10 UTC Modified: 2018-12-18 14:17 UTC
From: sscannell at ripstech dot com Assigned: cmb (profile)
Status: Not a bug Package: GD related
PHP Version: 7.2.13 OS: *
Private report: No CVE-ID: None
 [2018-12-17 15:10 UTC] sscannell at ripstech dot com
Description:
------------
Image resources in GD are represented by the gdImage struct. Images can be created via the PHP userland functions imagecreate and imagecreatetruecolor and return such a resource.

via imagesettile (http://php.net/manual/de/function.imagesettile.php) one image resource can then be set as a "tile" for another image. A pointer to the underlying gdImage Struct of the tile is then set as the value of the tile field of the image resource that should have the tile:

void gdImageSetTile (gdImagePtr im, gdImagePtr tile)
{
	int i;
	im->tile = tile;
...


The issue is that only a pointer to the struct is passed, meaning all information about the refcount is then lost. By freeing the tile, creating a string of the same size as the just freed tile an attacker can read arbitrary memory memory.

The same happens for brushes:

void gdImageSetBrush (gdImagePtr im, gdImagePtr brush)
{
	int i;
	im->brush = brush;
...




Test script:
---------------
<?php

$img = imagecreate(0xff, 0xff);
$tile = imagecreate(0xff, 0xff);
imagesettile($img, $tile);
imagedestroy($tile);
$str = str_repeat("\x00", 7360 - 32);
imagesetpixel($img, 0, 0, -5);


Expected result:
----------------
No crash

Actual result:
--------------
Floating point exception (core dumped)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-12-18 14:17 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Type: Security +Type: Bug -Assigned To: +Assigned To: cmb
 [2018-12-18 14:17 UTC] cmb@php.net
> By freeing the tile, creating a string of the same size as the
> just freed tile an attacker can read arbitrary memory memory.

Firstly, we must not assume that an attacker can execute arbitrary
PHP code – otherwise all bets are off.

Secondly, the PHP manual already documents this issue[1][2]:

| You need not take special action when you are finished with a
| tile, but if you destroy the tile image, you must not use the
| IMG_COLOR_TILED color until you have set a new tile image!

So according to our security classification[3], this is not a
security issue, since it requires the use of code or settings
known to be insecure.

I admit that this behavior of the GD extension is not nice, but
since the extension works with resources, there is no way to
cleanly solve this with refcounting only, since there may be
cyclic references between images, which would require a garbage
collector.  Switching to objects would allow us to resolve this.

[1] <http://php.net/manual/en/function.imagesettile.php#refsect1-function.imagesettile-description>
[2] <http://php.net/manual/en/function.imagesetbrush.php#refsect1-function.imagesetbrush-notes>
[3] <https://wiki.php.net/security>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Apr 29 00:01:32 2024 UTC