{"uuid": "401d7731-6e4d-4b2e-91a6-24c1b529ebf7", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-34197", "type": "seen", "source": "https://gist.github.com/Nayeraneru/bd66a0b4d4667e41feb2d2b5b73ec431", "content": "# GSoC 2026 Final Report \u2014 Automated Vulnerable Environment Provisioning for Metasploit\n\n**Student:** Nayera Ahmed Shafik Mostafa  \n**Organization:** Metasploit  \n**Mentors:** Spencer McIntyre, h00die  \n**Project:** `test_env` \u2014 A Metasploit Plugin for Automated Vulnerable Environment Provisioning  \n**Final Pull Request:** https://github.com/rapid7/metasploit-framework/pull/21895 \n\n---\n\n## 1. Project Goals\n\nMetasploit is the de-facto standard for exploit development and security validation, yet setting up a vulnerable target environment remains a manual, out-of-band process. Users must read module documentation, hunt for Docker images, guess port mappings, and manually configure datastore options (`RHOSTS`, `RPORT`, credentials) before they can fire an exploit. This friction hurts reproducibility, slows down module development, and makes automated CI verification nearly impossible.\n\nThe goal of this project was to build a **first-class, native Metasploit workflow** that collapses this entire pipeline into a single command:\n\n```\nmsf &gt; use exploit/multi/http/apache_activemq_jolokia_rce\nmsf exploit(...) &gt; test_env build\n[+] Environment ready.\n```\n\nSpecifically, the project aimed to:\n\n1. **Automate provisioning** \u2014 Pull OCI images, allocate free host ports, launch containers, and health-check the service.\n2. **Preserve exploit context** \u2014 Automatically bind `RHOSTS`, `RPORT`, credentials, and other datastore options to the module.\n3. **Support lifecycle management** \u2014 Track, stop, start, and clean up environments across `msfconsole` restarts.\n4. **Enable CI validation** \u2014 Share the same environment definitions between local development and headless CI runners.\n5. **Require zero framework core changes** \u2014 Deliver everything as a self-contained plugin with opt-in module metadata.\n\n---\n\n## 2. What I Did\n\n### 2.1 Core Plugin (`plugins/test_env.rb`)\n\nA ~2,000-line Ruby plugin that adds the `test_env` command family to `msfconsole`. Key subsystems:\n\n| Subsystem | Responsibility |\n|-----------|----------------|\n| **Runtime Adapter** (`DockerRuntime`, `PodmanRuntime`) | Unified container abstraction with auto-detection. Podman includes rootless networking validation (`pasta` / `slirp4netns`). |\n| **Port Allocator** | Finds free ephemeral host ports, scanning both the local registry and actively bound runtime ports to avoid collisions with orphaned containers from previous sessions. |\n| **Health Manager** | Configurable readiness checks (`http`, `tcp`, `command`) with retry logic, timeouts, and Basic Auth support. |\n| **Provisioner** | One-time setup actions (e.g., driving the WordPress install wizard via HTTP POST) that run after health checks pass but before the environment is registered as ready. |\n| **Registry** (`BuiltEnvironmentRegistry`) | ActiveModel-backed YAML persistence in `~/.msf4/test_env_registry.yml` with POSIX file locking for safe multi-process access. Reconstructs state from OCI container labels on startup. |\n| **Command Dispatcher** | Routes `test_env build`, `list`, `modules`, `stop`, `start`, `remove`, `remove-all`, `exec`, `validate`, `status`, and `help`. |\n\n### 2.2 Environment Definition Schema (`data/vuln_envs/*.yml`)\n\nA YAML schema that serves as the **single source of truth** for a vulnerable service:\n\n- **`variants`** \u2014 Software versions / images (e.g., ActiveMQ `5.18.6` vs `5.18.2`).\n- **`shared`** \u2014 Base ports, credentials, health checks, datastore defaults, provisioning steps, and CI metadata.\n- **`profiles`** \u2014 Runtime configurations (e.g., `default` vs `broker-only`) via deep-merge overrides.\n- **`ci.exploit`** \u2014 Recommends payloads known to work against the image (e.g., avoiding a broken default).\n- **`ci.validation`** \u2014 Defines what \"success\" means (session type, expected command output).\n\nDefinitions shipped in this PR:\n\n- **`activemq.yml`** \u2014 Apache ActiveMQ Classic with Jolokia API (CVE-2026-34197).\n- **`wordpress.yml`** \u2014 Vulnerable WordPress with one-time install wizard provisioning + verification.\n- **`httpd.yml`** \u2014 Apache HTTP Server for auxiliary scanner testing.\n- **`openssh.yml`** \u2014 OpenSSH server for SSH scanner testing.\n\n### 2.3 Module Integration\n\nIntroduced `VulnerableEnvironment`, a new metadata key inside `update_info()` that follows the exact same framework pattern as `Name`, `Description`, `Notes`, etc.:\n\n```ruby\n'VulnerableEnvironment' =&gt; {\n  'definition'      =&gt; 'activemq',\n  'default_variant' =&gt; '5.18.6',\n  'profile'         =&gt; 'default',\n  'port_mapping'    =&gt; { 8161 =&gt; 'RPORT' }\n}\n```\n\nThe reference integration is on **`modules/exploits/multi/http/apache_activemq_jolokia_rce.rb`**.\n\n### 2.4 CI Integration\n\nReplaced static container definitions with environment-driven provisioning in GitHub Actions:\n\n- **`.github/workflows/test_env.yml`** \u2014 A matrix job that consumes the same YAML definitions as local users, validating shared definitions, health checks, datastore automation, and exploit execution across exploit and auxiliary modules.\n- **`scripts/ci_runner.sh`** \u2014 A headless msfconsole runner that bridges `PASS`/`FAIL` output to standard Unix exit codes for CI.\n\n### 2.5 Documentation\n\n- **`DEVELOPER_Doc.md`** \u2014 Complete schema reference, three-level merge hierarchy (`shared` \u2192 `profile` \u2192 `module overrides`), validation rules, and a step-by-step guide for authoring new definitions.\n- **`USER_Doc.md`** \u2014 Interactive usage guide, command reference with real console transcripts, typical workflows (interactive dev, multi-version testing, auxiliary scanning, resume-after-restart), and troubleshooting.\n\n---\n\n## 3. Current State\n\nThe project is **feature-complete** and **under final review** by the Rapid7 engineering team.\n\n### What was accomplished\n\n- \u2705 **Architecture design** (documented in Markdown): command dispatcher, module metadata, database schema, environment schema, runtime adapter\n- \u2705 **`test_env build`** \u2014 19-step pipeline: validate \u2192 resolve definition \u2192 pull image \u2192 allocate ports \u2192 launch \u2192 health check \u2192 provision \u2192 register \u2192 apply datastore\n- \u2705 **`test_env exec `** \u2014 Auto-loads module, applies stored datastore + recommended payload, allocates fresh `SRVPORT`/`FETCH_SRVPORT`\n- \u2705 **`test_env validate `** \u2014 Verifies sessions against `ci.validation` (session type, command output); works for exploit + auxiliary modules\n- \u2705 **`test_env modules`** \u2014 Discovers all modules with `VulnerableEnvironment` support\n- \u2705 **Lifecycle commands** \u2014 `list`, `stop`, `start`, `remove`, `remove-all` with range parsing (`1-3,5`)\n- \u2705 **Cross-session persistence** \u2014 YAML registry + container label reconstruction\n- \u2705 **Docker &amp; Podman support** \u2014 including rootless Podman networking checks\n- \u2705 **CI matrix** \u2014 validating 8 module/definition combinations (exploit + auxiliary)\n- \u2705 **Full documentation** \u2014 user + developer guides\n---\n\n## 4. Future Work\n\nWhile the core plugin is complete, the following are natural extensions for the community:\n\n1. **More environment definitions** \u2014 The schema is designed for scale. Adding new services only requires a YAML file + module metadata.\n2. **Multi-request provisioning** \u2014 Extend the provisioner to support cookie/session carryover for multi-step install wizards.\n3. **Non-HTTP provisioning** \u2014 Add `type: command` provisioning for images that need a shell command rather than an HTTP POST.\n\n---\n\n## 5. Code &amp; Pull Requests\n\n### Weekly Development (Mentor-Reviewed)\n\nDevelopment was done in 12 incremental pull requests in my forked repository, each reviewed weekly by my mentors:\n\n- Week 1: [`vulnenv-week1`](https://github.com/Nayeraneru/metasploit-framework/pull/1)\n- Week 2: [`vulnenv-week2`](https://github.com/Nayeraneru/metasploit-framework/pull/3)\n- Week 3: [`vulnenv-week3`](https://github.com/Nayeraneru/metasploit-framework/pull/4)\n- Week 4: [`vulnenv-week4`](https://github.com/Nayeraneru/metasploit-framework/pull/5)\n- Week 5: [`vulnenv-week5`](https://github.com/Nayeraneru/metasploit-framework/pull/6)\n- Week 6: [`vulnenv-week6`](https://github.com/Nayeraneru/metasploit-framework/pull/7)\n- Week 7: [`vulnenv-week7`](https://github.com/Nayeraneru/metasploit-framework/pull/8)\n- Week 8: [`vulnenv-week8`](https://github.com/Nayeraneru/metasploit-framework/pull/9)\n- Week 9: [`vulnenv-week9`](https://github.com/Nayeraneru/metasploit-framework/pull/10)\n- Week 10: [`vulnenv-week10`](https://github.com/Nayeraneru/metasploit-framework/pull/11)\n- Week 11: [`vulnenv-week11`](https://github.com/Nayeraneru/metasploit-framework/pull/12)\n- Week 12: [`vulnenv-week12`](https://github.com/Nayeraneru/metasploit-framework/pull/15)\n\nAll 12 branches were merged into the **`vulnenv`** integration branch.\n\n### Final Upstream Pull Request\n\n**[\u2192 Link to PR: `vulnenv` \u2192 `master` on `rapid7/metasploit-framework`](https://github.com/rapid7/metasploit-framework/pull/21895)**\n\nThis is the single PR currently under review by the Rapid7 engineering team. Each weekly PR linked above contains a detailed description of its respective changes.\n\n---\n\n## 6. Challenges &amp; Lessons Learned\n\n1. **Cross-session state loss** \u2014 Solved with a YAML registry (`File.flock` for safety) + container-label reconstruction. *Lesson: container runtime is ground truth; registry is a cache.*\n\n2. **Port collisions with orphaned containers** \u2014 A port can test free yet be bound by a stale container. *Lesson: check the OS **and** the runtime.*\n\n3. **Broken default payloads** \u2014 ActiveMQ's auto-payload uses FTP, which Metasploit's fetch server doesn't support; added `ci.exploit.payload` overrides. *Lesson: environment definitions know the image better than modules.*\n\n4. **Process-local sessions** \u2014 Sessions die with their `msfconsole`; `exec`/`validate` must share one instance. *Lesson: document constraints honestly, don't hide them.*\n\n5. **WordPress not truly ready** \u2014 Apache ran, but no schema/admin existed; added `provision` + `verify` (install wizard POST + login-page health check). *Lesson: \"process running\" \u2260 \"application ready\" \u2014 verify the exploitable state.*\n\n---\n\n## 7. Acknowledgments\n\nHuge thanks to my mentors **Spencer McIntyre** and **h00die** for their weekly reviews, architectural guidance, and patience through 12 iterations. This project would not have been possible without the Metasploit community's excellent codebase and documentation.\n", "creation_timestamp": "2026-09-12T15:22:56.555476Z"}