# Apache HTTP [2.4.17-2.4.38] Local Root Privilege Escalation

Apache HTTP 2.4.17-2.4.38 prefork/worker/event MPMs trust an unvalidated worker-controlled bucket index in shared memory, yielding an arbitrary function call as root on graceful restart.

- Payout: $1,500
- Severity: high
- Program: Internet Bug Bounty
- Credited: real
- Disclosed: 2019-09-11
- CVE: CVE-2019-0211, CVE-2019-6977
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/520903
- Library page: https://bugbountylibrary.com/r/h1%3A520903
- Tags: domain:infra impact:privesc impact:rce kind:bounty platform:hackerone sev:high tech:linux tech:php technique:chained technique:source-review vuln:memory-corruption vuln:privilege-escalation

**Target:** Apache HTTP Server MPM prefork/worker/event scoreboard shared memory
**Root cause:** The main root process reads process_score.bucket from the worker-writable scoreboard SHM and indexes all_buckets[] without bounds checks, then calls mutex->meth->child_init() before dropping privileges.
**Steps:**
1. Gain R/W in a www-data worker (e.g. PHP UAF CVE-2019-0211 exploit via mod_php) to read /proc/self/maps and edit SHM.
2. Locate ap_scoreboard_image->parent[] in the rw-s /dev/zero SHM mapping and all_buckets by scanning for a prefork_child_bucket whose mutex->meth points into libapr .data/.text.
3. Write a fake prefork_child_bucket into SHM with mutex->meth->child_init pointing to zend_object_std_dtor and craft object->properties so pDestructor=system and arData[0]->val is the command.
4. Set a process_score.bucket to the index pointing at the fake structure; spray SHM across all process_score slots to survive all_buckets reallocation.
5. Wait for logrotate's `apache2ctl graceful` (~06:25) so the root parent forks a replacement worker and invokes child_init() as root.
**How found:** Code review of prefork.c restart path: noticed process_score.bucket from worker-writable SHM is passed to make_child() and used to index all_buckets without bounds checks, then traced to mutex->meth->child_init() before privilege drop.
**Exploitation:** Rogue worker edits SHM bucket index and plants a fake mutex structure; on graceful restart the root parent calls the attacker-chosen function pointer before setuid, executing system() as root.
**Escalation:** Chains a PHP 7.x UAF (zend_object to zend_string len corruption) for arbitrary R/W to reach SHM and all_buckets, then abuses the root restart path for full local root.
**Insight:** Shared-memory scoreboards written by low-priv workers and later consumed by the root parent are a trust-boundary goldmine; grep for SHM fields used as array indexes in the privileged process, especially on restart/reload paths.
