# PHP Heap Overflow Vulnerability in imagecrop()

PHP imagecrop() in gd extension mishandles user-supplied crop dimensions, allowing integer overflow, out-of-bounds reads, and heap buffer overflow via crafted x/width values.

- Payout: hidden
- Severity: high
- Program: Internet Bug Bounty
- Found by: kubabrecka
- Disclosed: 2014-02-06
- CVE: CVE-2013-7226
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/1356
- Library page: https://bugbountylibrary.com/r/h1%3A1356
- Tags: area:oss domain:oss impact:data-leak impact:dos kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:dos vuln:info-disclosure vuln:memory-corruption

**Target:** PHP gd extension imagecrop()/gdImageCrop()
**Root cause:** imagecrop() passes user-supplied dimensions to gdImageCrop() without type checks or integer-overflow-safe bounds checks; signed arithmetic in the bounds check can be overflown, and the return value of gdImageCreate* is not checked.
**Steps:**
1. Call imagecrop() with a dimensions array whose 'x' is a string/array to leak pointers (POC 1: `array("x" => "a", "y" => 0, "width" => 10, "height" => 10)`).
2. Pass negative width to trigger NULL-pointer write from unchecked gdImageCreate return (POC 2: `array("x" => 0, "y" => 0, "width" => -1, "height" => 10)`).
3. Pass negative x/y to force out-of-bounds read of source pixels (POC 3: `array("x" => -20, "y" => -20, "width" => 10, "height" => 10)`).
4. Pass very large x to overflow the signed bounds check so crop->width exceeds destination buffer, causing heap overflow in memcpy (POC 4: `array("x" => 0x7fffff00, "y" => 0, "width" => 10, "height" => 10)`).
**How found:** Code review of ext/gd/gd.c and gdImageCrop(): noticed missing type check on zval, unchecked gdImageCreate return, and signed arithmetic in bounds checks that can be overflown with large x.
**Exploitation:** A remote attacker controlling image data and crop dimensions in a PHP image-processing script can supply crafted x/y/width/height values to trigger OOB reads (info leak), NULL writes (crash/DoS), or a heap buffer overflow in the memcpy of pixel rows, potentially leading to memory corruption.
**Escalation:** Info leak via string/array zval treated as integer can leak pointers usable for subsequent exploitation; heap overflow can corrupt heap metadata.
**Insight:** When auditing image/crop APIs, check whether dimension bounds checks use signed arithmetic that can wrap, and whether allocation return values are validated before writes; negative offsets into pixel buffers are a reliable OOB read primitive.

## Proof of concept (copied exactly from the original report)

**PoC 4 heap overflow via large x**

```
<?
// POC 4
$img = imagecreatetruecolor(10, 10);
$img = imagecrop($img, array("x" => 0x7fffff00, "y" => 0, "width" => 10, "height" => 10));
```

**PoC 3 negative x/y out-of-bounds read**

```
<?
// POC 3
$img = imagecreatetruecolor(10, 10);
$img = imagecrop($img, array("x" => -20, "y" => -20, "width" => 10, "height" => 10));
```

**PoC 2 negative width NULL write**

```
<?
// POC 2
$img = imagecreatetruecolor(10, 10);
$img = imagecrop($img, array("x" => 0, "y" => 0, "width" => -1, "height" => 10));
```

