{"repro_id":"REPRO-2026-00072","version":8,"title":"Apache bRPC: Remote Command Injection in Heap Profiler","repro_type":"security","status":"published","severity":"high","description":"Remote command injection in heap profiler endpoint via unsanitized extra_options parameter in Apache bRPC.","root_cause":"# Root Cause Analysis - CVE-2025-60021\n\n## Summary\nApache bRPC versions 1.11.0 through 1.14.x allow remote command injection via the built-in `/pprof/heap` endpoint when jemalloc profiling is enabled. The handler concatenates the user-controlled `extra_options` query parameter directly into a shell command used to invoke `jeprof`, and the command is executed through `popen`, allowing shell metacharacters to execute arbitrary commands.\n\n## Impact\n- **Component:** `src/brpc/details/jemalloc_profiler.cpp` (jemalloc heap profiler endpoint `/pprof/heap`)\n- **Affected versions:** 1.11.0 to <1.15.0\n- **Risk level:** Important — remote command execution as the service user, enabling data exfiltration and lateral movement.\n\n## Root Cause\nThe heap profiler handler builds a command line for `jeprof` and appends the `extra_options` query parameter without validation:\n- Vulnerable code (1.14.1): `cmd_str += \" --\" + *uri_extra_options + \" \";`\n- The command is executed via `butil::read_command_output`, which uses `popen()` (`/bin/sh -c`), so shell metacharacters in `extra_options` are interpreted.\n\nThe fix in 1.15.0 introduces a whitelist of allowed `extra_options` values and ignores unsupported inputs, preventing shell metacharacter injection. See PR https://github.com/apache/brpc/pull/3101.\n\n## Reproduction Steps\n1. Run `repro/reproduction_steps.sh`.\n2. The script builds bRPC 1.14.1 and 1.15.0, starts the echo server with jemalloc profiling enabled, then issues crafted `/pprof/heap` requests.\n3. Expected evidence: `uid=...` appears in `logs/vuln_response.txt` for 1.14.1 and is absent in `logs/fixed_response.txt` for 1.15.0.\n\n## Evidence\n- Vulnerable response (1.14.1): `logs/vuln_response.txt`\n  - `uid=0(root) gid=0(root) groups=0(root)` (line 82)\n- Fixed response (1.15.0): `logs/fixed_response.txt`\n  - No `uid=` output present.\n- Build and runtime logs:\n  - `logs/echo_server_vuln.log`\n  - `logs/echo_server_fixed.log`\n\nEnvironment details:\n- Ubuntu with system dependencies installed via `apt-get`.\n- jemalloc enabled via `MALLOC_CONF=prof:true` and `LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2`.\n\n## Recommendations / Next Steps\n- Upgrade to bRPC 1.15.0 or apply the whitelist patch from PR #3101.\n- Consider avoiding shell execution entirely (pass arguments directly to `execve` without shell) for any future tooling.\n- Add regression tests for `/pprof/heap` to ensure only approved options are accepted.\n\n## Additional Notes\n- Idempotency verified: `repro/reproduction_steps.sh` executed twice successfully.\n- The exploit only applies when jemalloc profiling is enabled and `/pprof/heap` is reachable.","cve_id":"CVE-2025-60021","source_url":"https://lists.apache.org/thread/xy51d2fx6drzhfp92xptsx5845q7b37m","package":{"name":"brpc","ecosystem":"cpp","affected_versions":"1.11.0 to <1.15.0","fixed_version":"1.15.0"},"reproduced_at":"2026-01-21T06:18:18.719971+00:00","duration_secs":2873.2288975715637,"tool_calls":503,"handoffs":4,"quality":{"idempotent_verified":false,"community_verifications":0},"evidence":{"evidence_output":"uid=0(root) gid=0(root) groups=0(root)","fix_pr":"https://github.com/apache/brpc/pull/3101","fixed_version":"1.15.0","injection_payload":";id;true","vulnerability_confirmed":true,"vulnerable_endpoint":"/pprof/heap?extra_options=;id;true","vulnerable_file":"src/brpc/details/jemalloc_profiler.cpp","vulnerable_version":"1.14.1"},"key_moments":[{"agent":"repro","description":"Agent clones the Apache bRPC repository to analyze the vulnerable code and prepare for reproduction testing.","index":31,"time":41959,"title":"Cloning brpc repository","type":"env_setup"},{"agent":"repro","description":"Agent diffs version 1.14.1 (vulnerable) against 1.15.0 (fixed) to understand how command injection via extra_options parameter was patched by adding whitelist validation.","index":59,"time":93521,"title":"Analyzing the security fix","type":"vuln_analysis"},{"agent":"repro","description":"Injected shell command via extra_options parameter successfully executes - curl request with \";id;\" payload returns \"uid=0(root) gid=0(root)\" proving remote command execution.","index":240,"time":849296,"title":"Command injection confirmed","type":"vuln_triggered"},{"agent":"repro","description":"Agent writes comprehensive reproduction_steps.sh that builds vulnerable and fixed versions, tests command injection, and validates the fix prevents exploitation.","index":279,"time":1335536,"title":"Reproduction script written","type":"poc_created"}],"published_at":"2026-01-21T06:18:20.494534+00:00","retracted":false,"artifacts":[{"path":"repro/reproduction_steps.sh","filename":"reproduction_steps.sh","size":3871,"category":"reproduction_script"},{"path":"repro/rca_report.md","filename":"rca_report.md","size":2637,"category":"analysis"},{"path":"coding/proposed_fix.diff","filename":"proposed_fix.diff","size":3212,"category":"patch"},{"path":"bundle/ticket.md","filename":"ticket.md","size":1884,"category":"ticket"},{"path":"coding/summary_report.md","filename":"summary_report.md","size":912,"category":"documentation"},{"path":"coding/verify_fix.sh","filename":"verify_fix.sh","size":525,"category":"other"},{"path":"logs/memory.json","filename":"memory.json","size":478,"category":"other"},{"path":"logs/repro_tool_calls.json","filename":"repro_tool_calls.json","size":254393,"category":"other"}]}