# Buffer overflow in HTTP url parsing functions

Heap buffer overflow in PHP pecl_http URL parsing percent-encodes non-printable chars without bounds checks, overwriting adjacent php_stream_ops function pointers toward code execution.

- Payout: hidden
- Severity: high
- Program: Internet Bug Bounty
- Found by: rc0r
- Disclosed: 2016-07-28
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/121863
- Library page: https://bugbountylibrary.com/r/h1%3A121863
- Tags: area:oss domain:oss impact:rce kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:memory-corruption vuln:rce

**Target:** php_http_url.c parse_* functions in pecl_http extension
**Root cause:** parse_mb() and sibling parse_* functions increment state->offset three times per non-printable byte when percent-encoding, without checking remaining size of state->buffer, so a crafted URL overflows the heap allocation.
**Steps:**
1. Build PHP with --with-http (pecl_http 2.5.x/3.0.x).
2. Craft poc.req containing a URL with many non-printable bytes so percent-encoding expands past buffer size.
3. Run `new http\Message(file_get_contents("poc.req"), false);` to trigger php_http_url_parse.
4. Observe state->buffer overflow overwriting adjacent php_stream_ops struct.
5. On stream free, `call QWORD PTR [rax+0x10]` invokes the corrupted close callback pointer.
**How found:** Code review of php_http_url.c parse_* functions noticed state->offset incremented three times per byte during percent-encoding with no bounds check against state->buffer size; gdb tracing confirmed adjacent php_stream_ops struct corruption and callback invocation.
**Exploitation:** Attacker supplies a malicious HTTP message/URL to http\Message parsing; percent-encoding of non-printable bytes overflows the heap buffer, corrupting the adjacent php_stream_ops struct's function pointers. When the stream is freed, _php_stream_free calls stream->ops->close, redirecting execution to attacker-influenced address (lower 3 bytes overwritten), yielding control-flow hijack toward arbitrary code execution.
**Escalation:** Partial pointer overwrite (lower 3 bytes + trailing null) of a callback invoked on stream free converts a heap overflow into a controlled indirect call.
**Insight:** When auditing parsers that expand input (percent-encoding, escaping), check whether the output offset is bounds-checked against the allocation; adjacent heap objects with function pointers (like php_stream_ops) turn a linear overflow into control-flow hijack via a single partial overwrite.

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

**PHP PoC script parsing malicious request file**

```
<?php
 $http_msg = new http\Message(file_get_contents("poc.req"), false);
?>
```

