# PHP Session Data Injection Vulnerability

PHP's php/php_binary session deserializers skip disallowed session names but keep parsing, letting attacker-controlled session keys inject arbitrary serialized data and objects.

- Payout: hidden
- Severity: high
- Program: Internet Bug Bounty
- Found by: ryat
- Disclosed: 2019-10-13
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/159946
- Library page: https://bugbountylibrary.com/r/h1%3A159946
- Tags: area:oss domain:oss impact:integrity kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:deserialization

**Target:** PHP session serialize handlers (php, php_binary)
**Root cause:** PS_SERIALIZER_DECODE_FUNC(php) skips disallowed session names (e.g. _SESSION, http_session_vars) via goto skip but continues parsing the remaining buffer, so a crafted key like `_SESSION` embeds a serialized payload that is later deserialized as session data.
**Steps:**
1. Set `session.serialize_handler` to `php` and call `session_start()`.
2. Assign `$_SESSION['_SESSION'] = 'ryat|O:8:"stdClass":0:{}';` and call `session_write_close()`.
3. Call `session_start()` again; the decoder skips the `_SESSION` name but continues parsing, injecting `ryat|O:8:"stdClass":0:{}` as session data.
4. `var_dump($_SESSION)` shows the injected serialized object, demonstrating arbitrary session data injection.
**How found:** Code review of the php session serializer decode loop: noticed the `goto skip` path frees the name and advances `p = q` but does not stop parsing, so skipped names still leave their value bytes in the buffer to be parsed as a new key/value pair.
**Exploitation:** Any app that lets user input reach session keys (e.g. `$_SESSION = array_merge($_SESSION, $_POST)` or `$_SESSION[$_GET['id']] = $_GET['result']`) allows an attacker to place a serialized payload under a skipped name, which is then deserialized, enabling object injection and use-after-free similar to unserialize() on user input.
**Escalation:** Chains to object injection / use-after-free when the injected serialized data is deserialized by application code.
**Insight:** In deserializer loops, a 'skip' branch that continues parsing the same buffer can turn a rejected key into attacker-controlled data for the next iteration; check whether skip paths advance past the value, not just the name.

