# Null Pointer Dereference in PHP Session Upload Progress

With session.upload_progress.cleanup=0, a failed multipart upload skips FILE_START, leaving progress->data uninitialized; SEPARATE_ARRAY then dereferences it, crashing PHP remotely.

- Payout: hidden
- Severity: medium
- Program: Internet Bug Bounty
- Found by: ryat
- Disclosed: 2020-11-09
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/798744
- Library page: https://bugbountylibrary.com/r/h1%3A798744
- Tags: area:web domain:web impact:dos kind:bounty platform:hackerone sev:medium tech:php technique:source-review vuln:dos vuln:memory-corruption

**Target:** PHP session upload progress (rfc1867) multipart handler
**Root cause:** When cleanup is disabled and the upload fails before MULTIPART_EVENT_FILE_START, progress->data remains an uninitialized zero ZVAL; MULTIPART_EVENT_END calls SEPARATE_ARRAY on it, dereferencing a null pointer.
**Steps:**
1. Set session.upload_progress.cleanup=0 in php.ini (e.g. `php -S localhost:8000 -t /www/web/ -d session.upload_progress.cleanup=0`)
2. Send a multipart POST to any PHP script with fields `PHPSESSID=session-upload` and `PHP_SESSION_UPLOAD_PROGRESS=ryat`, with no valid file part so FILE_START never fires
3. Server reaches MULTIPART_EVENT_END, calls SEPARATE_ARRAY(&progress->data) on the uninitialized ZVAL, and crashes
**How found:** Code review of session.c: noticed progress is ecalloc'd to zeros, data only initialized in MULTIPART_EVENT_FILE_START, but SEPARATE_ARRAY in MULTIPART_EVENT_END assumes it is initialized; hypothesized a failed upload path skips FILE_START.
**Exploitation:** Remote unauthenticated attacker sends a crafted multipart request to any PHP endpoint; no special server-side script needed. The malformed upload skips FILE_START, triggering the null dereference and crashing the PHP process/server.
**Insight:** In multipart/session state machines, audit event handlers that assume a prior event (FILE_START) always fired; a malformed or failing upload can skip intermediate events and reach END with zeroed structs.

