# PHP OpenSSL zif_openssl_seal() heap overflow (wild memcpy)

Malformed PEM cert makes EVP_SealInit return -1, leaving eksl[0]=-1, causing a wild memcpy heap overflow in PHP's openssl_seal() and crashing the server.

- Payout: $500
- Severity: medium
- Program: Internet Bug Bounty
- Credited: xixabangm4
- Disclosed: 2019-10-14
- CVE: CVE-2017-11144
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/248609
- Library page: https://bugbountylibrary.com/r/h1%3A248609
- Tags: domain:oss impact:dos kind:bounty platform:hackerone sev:medium tech:php technique:reverse-engineering technique:source-review vuln:dos vuln:memory-corruption

**Target:** PHP ext/openssl zif_openssl_seal()
**Root cause:** PHP ignores EVP_SealInit()'s -1 error return and passes eksl[i]=-1 as a length to add_next_index_stringl(), triggering a negative-size memcpy; also negative-indexes eks[i][eksl[i]].
**Steps:**
1. Craft a PEM certificate whose public key yields a negative key length during EVP_PKEY_encrypt_old.
2. Call `openssl_get_publickey($pem)` then `openssl_seal($data,$sealed,$ekeys,array($key,$key),'AES-128-ECB')`.
3. EVP_SealInit returns -1 and sets eksl[0]=-1.
4. PHP executes `eks[i][eksl[i]]='\0'` (negative index) then `add_next_index_stringl(...,eksl[i])` with size -1.
5. ASan reports negative-size-param in __asan_memcpy via zend_string_init; process aborts.
**How found:** Researcher fuzzed/parsed a PEM certificate through openssl_seal() and observed an invalid key length after parsing; GDB watchpoint on eksl[0] showed EVP_SealInit setting it to -1, tracing the bad length into add_next_index_stringl.
**Exploitation:** Any code path that calls openssl_seal() with an attacker-supplied certificate triggers an immediate DoS crash; potential code execution depends on exploitability of the wild memcpy and requires a malicious external certificate.
**Insight:** When a crypto API returns a length out-param, watch for error returns like -1 being stored into that length and later used as a memcpy size or array index; a GDB hardware watchpoint on the length array pinpoints the exact library call that poisons it.
