# SoapClient's __call() type confusion through unserialize()

SoapClient::__call() trusts unserialized __default_headers as an array, so a crafted integer causes type confusion and memory corruption leading to RCE.

- Payout: hidden
- Severity: high
- Program: Internet Bug Bounty
- Found by: cogitoergor00t
- Disclosed: 2015-03-03
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/55030
- Library page: https://bugbountylibrary.com/r/h1%3A55030
- Tags: area:oss domain:oss kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:deserialization vuln:memory-corruption vuln:rce

**Target:** PHP SoapClient extension (soap.c)
**Root cause:** In soap.c:2906, Z_ARRVAL_P is applied to the __default_headers property without verifying it is actually an array; unserialize() lets an attacker set it to an arbitrary type such as an integer.
**Steps:**
1. Craft serialized object `O:10:"SoapClient":3:{s:3:"uri";s:1:"a";s:8:"location";s:22:"http://localhost/a.xml";s:17:"__default_headers";i:1337;}`
2. Pass it to `unserialize()`
3. Invoke any method on the object, e.g. `$dummy->whatever()`, to trigger `__call()`
4. Observe SIGSEGV in `zend_hash_internal_pointer_reset_ex` with `$rdi=1337`
**How found:** Code review of soap.c's __call() implementation spotted Z_ARRVAL_P applied to __default_headers with no type check, then a minimal unserialize payload confirmed the crash.
**Exploitation:** Any code path that unserializes attacker-controlled input and then calls a method on the resulting SoapClient object triggers the type confusion; the bogus pointer (1337) is dereferenced as a HashTable, giving crash and potentially arbitrary read/write and code execution.
**Insight:** Magic methods like __call() that read object properties after unserialize() are prime type-confusion targets: look for Z_ARRVAL_P/Z_STRVAL_P macros applied to properties without a preceding Z_TYPE check.

