Skip to content
Closed
49 changes: 49 additions & 0 deletions data/vuln_envs/jenkins.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: jenkins
description: Jenkins CI server with Groovy Script Console enabled

versions:
"2.361":
image: vulnhub/jenkins:2.361
build_args:
JENKINS_VERSION: "2.361"
"2.375":
image: vulnhub/jenkins:2.375
build_args:
JENKINS_VERSION: "2.375"

shared:
ports:
http: 8080

volumes:
jenkins_home:
container_path: /var/jenkins_home
persist: false

health_check:
type: http
path: /login
expected_status: 200
interval: 5
timeout: 2
retries: 12

credentials:
default:
username: admin
password: admin

datastore_defaults:
TARGETURI: /script

ci:
exploit:
payload: java/meterpreter/reverse_tcp
options:
LHOST: 127.0.0.1
LPORT: 4444
validation:
expected_session: true
session_type: meterpreter
expected_output: "uid="
timeout: 120
194 changes: 194 additions & 0 deletions docs/ci_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# CI Workflow: Automated Exploit Verification



This document defines how `test_env` will be used in GitHub Actions to automatically:
- Provision vulnerable environments from shared definitions
- Execute exploits with pre-configured datastore options
- Validate expected outcomes (session creation, command output)
- Clean up all containers to prevent resource leaks

**Key principle:** CI consumes the same environment definitions used for local testing. No duplicated container configuration.


## Directory Structure

This directory structure will created as part of the project:

```
metasploit-framework/
├── ci/
│ ├── test_activemq.rc
│ ├── test_jenkins.rc
│ └── test_drupal.rc
├── .github/
│ └── workflows/
│ └── vuln-env-test.yml
├── data/
│ └── vuln_envs/
│ ├── activemq.yml
│ ├── jenkins.yml
│ └── drupal.yml
└── docs/
└── ci_workflow.md
```



A **resource script** with a `.rc` extension that contains msfconsole commands. Instead of typing commands one by one into msfconsole, they will be saved in a file and run:

```bash
./msfconsole -q -r path/to/script.rc
```

Metasploit reads the file and executes each line automatically, as if it's typed.



### Example: ci/test_jenkins.rc

**What it is:** A text file containing msfconsole commands to test the Jenkins module automatically.

**What it contains:**
```text
load test_env
use exploit/multi/http/jenkins_script_console
test_env build VERSION=2.361
test_env exec 1
test_env remove-all
exit
```

**What each line does:**
| Line | Command | Purpose |
|------|---------|---------|
| 1 | `load test_env` | Load the test_env plugin |
| 2 | `use exploit/multi/http/jenkins_script_console` | Select the exploit module |
| 3 | `test_env build VERSION=2.361` | Build environment using Jenkins version 2.361 |
| 4 | `test_env exec 1` | Execute exploit against environment ID 1 |
| 5 | `test_env remove-all` | Stop and remove all containers |
| 6 | `exit` | Close msfconsole |

**How to run it manually (for testing):**
```bash
./msfconsole -q -r ci/test_jenkins.rc
```
---

## GitHub Actions Workflow

**What this is:** A YAML file that tells GitHub Actions what to do on every push or pull request.

**File:** `.github/workflows/vuln-env-test.yml`

**What it contains:**
```yaml
name: Vulnerable Environment Test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test-jenkins:
name: Test Jenkins Script Console
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true

- name: Set up Docker
uses: docker/setup-buildx-action@v3

- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-

- name: Run Jenkins exploit test
run: |
./msfconsole -q -r ci/test_jenkins.rc

- name: Verify session was created
run: |
grep "Session.*opened" ~/.msf4/logs/framework.log || echo "WARNING: No session log found"

- name: Verify no containers left behind
run: |
REMAINING=$(docker ps -q | wc -l)
if [ "$REMAINING" -eq 0 ]; then
echo "Clean: No containers remaining"
else
echo "FAIL: $REMAINING container(s) still running"
docker ps
exit 1
fi
```

**What each step does:**
| Step | Action | Purpose |
|------|--------|---------|
| Checkout | `actions/checkout@v4` | Download your code |
| Set up Ruby | `ruby/setup-ruby@v1` | Install Ruby 3.2 and gems |
| Set up Docker | `docker/setup-buildx-action@v3` | Install Docker |
| Cache Docker layers | `actions/cache@v3` | Speed up image pulls |
| Run exploit test | `./msfconsole -q -r ci/test_jenkins.rc` | Execute the Jenkins resource script |
| Verify session | `grep "Session.*opened"` | Confirm exploit succeeded |
| Verify cleanup | `docker ps -q` | Confirm no leaked containers |

---

## Validation Criteria

| Step | Expected Result | How It Is Checked | On Failure |
|------|----------------|-------------------|------------|
| `test_env build` | Container starts, health check passes | Console output contains "Environment ready" | Workflow fails |
| `test_env exec 1` | Session opens | `framework.log` contains "Session.*opened" | Workflow fails |
| `test_env remove-all` | All containers removed | `docker ps -q` returns empty | Workflow fails |
| Post-cleanup | Zero `msf.vulnenv` containers remain | `docker ps -a --filter "label=msf.vulnenv.managed_by=test_env"` returns empty | Workflow fails |

---

## CI Metadata in Environment Definitions

Environment definitions include a `ci` section so the automation knows what payload to use and what to validate:

```yaml
# data/vuln_envs/jenkins.yml
ci:
exploit:
payload: java/meterpreter/reverse_tcp
options:
LHOST: 127.0.0.1
LPORT: 4444
TARGETURI: /script
validation:
expected_session: true
session_type: meterpreter
expected_output: "uid="
timeout: 120
```

### Schema Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `ci.exploit.payload` | String | Yes | Payload to use for automated execution |
| `ci.exploit.options` | Hash | No | Datastore options: `LHOST`, `LPORT`, `TARGETURI`, etc. |
| `ci.validation.expected_session` | Boolean | Yes | Whether a session must be created |
| `ci.validation.session_type` | String | No | Expected session type: `meterpreter`, `shell` |
| `ci.validation.expected_output` | String | No | Substring to verify in session output |
| `ci.validation.timeout` | Integer | Yes | Max seconds to wait for validation |

48 changes: 48 additions & 0 deletions docs/reference_modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Reference Modules for test_env

## Selection Criteria
- Cover different service types: Java message broker (ActiveMQ), CI server (Jenkins), CMS (Drupal)
- Have clear, single-port (or well-defined multi-port) mappings
- Have existing Docker images with known vulnerable versions
- Demonstrate different health check patterns (API endpoint, login page, root page)
- Include both authenticated and unauthenticated exploit scenarios

---

## Module 1: Apache ActiveMQ Jolokia RCE (Mentor Suggested)
- **Path:** `exploit/multi/http/apache_activemq_jolokia_rce`
- **Type:** Java web application (JMX-over-HTTP)
- **Ports:** 8161 (web console / Jolokia API), 61616 (OpenWire broker)
- **Health Check:** HTTP GET `/api/jolokia/` expecting 200, or GET `/` expecting 200
- **Why:** h00die suggested PR #21497. Has a verified Docker one-liner. Real-world CVE-2026-34197.
- **VulnEnv Definition:** `activemq`
- **Docker Image:** `apache/activemq-classic:5.18.6`
- **Docker Run:** `docker run -d --name activemq -p 8161:8161 -p 61616:61616 apache/activemq-classic:5.18.6`
- **Credentials:** admin / admin
- **Exploit Context:** Requires authenticated Jolokia access; `TARGETURI` typically `/api/jolokia/`

---

## Module 2: Jenkins Script Console
- **Path:** `exploit/multi/http/jenkins_script_console`
- **Type:** Web application / CI server
- **Port:** 8080
- **Health Check:** HTTP GET `/login` expecting 200
- **Why:** Well-documented, multiple versions exist, clear RPORT→8080 mapping, widely used in exploit development tutorials
- **VulnEnv Definition:** `jenkins`
- **Docker Image:** `vulnhub/jenkins:2.361`
- **Credentials:** admin / admin
- **Exploit Context:** Script Console at `/script` allows Groovy execution; `TARGETURI` typically `/script`

---

## Module 3: Drupal Drupalgeddon2
- **Path:** `exploit/unix/webapp/drupal_drupalgeddon2`
- **Type:** Web application / CMS
- **Port:** 80
- **Health Check:** HTTP GET `/` expecting 200
- **Why:** Simple single-port setup, unauthenticated exploit, different architecture from ActiveMQ/Jenkins, large community interest
- **VulnEnv Definition:** `drupal`
- **Docker Image:** `vulnhub/drupal:CVE-2018-7600`
- **Credentials:** None required (unauthenticated)
- **Exploit Context:** SA-CORE-2018-002 (CVE-2018-7600); remote code execution via form API
50 changes: 50 additions & 0 deletions docs/test_env/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# test_env Design Documentation

This directory contains the architecture and workflow design for the `test_env` (VulnEnv) plugin.

## Architecture Documents

| Document | Description |
|----------|-------------|
| [01-command-dispatcher.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/architecture/01-command-dispatcher.md) | How `test_env` is added to msfconsole via plugin dispatcher |
| [02-module-metadata.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/architecture/02-module-metadata.md) | How modules expose `VulnEnv` metadata and how the plugin reads it |
| [03-database-schema.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/architecture/03-database-schema.md) | Registry persistence: in-memory Phase 1, PostgreSQL Phase 2 |
| [04-environment-schema.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/architecture/04-environment-schema.md) | YAML schema for shared environment definitions in `data/vuln_envs/` |
| [05-runtime-adapter.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/architecture/05-runtime-adapter.md) | Docker/Podman abstraction, port allocation, container labels |

## Workflow & Planning Documents

| Document | Description |
|----------|-------------|
| [reference_modules.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/reference_modules.md) | 3 reference modules selected for implementation (ActiveMQ, Jenkins, Drupal) |
| [workflow.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/workflow.md) | Target user workflows and console transcripts (acceptance criteria) |
| [ci_workflow.md](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/docs/test_env/ci_workflow.md) | GitHub Actions CI integration with resource scripts |

## Plugin File

- [plugins/test_env.rb](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/plugins/test_env.rb) — Main plugin implementation (Week 1 skeleton)

```
nayera@Nero:~/git/metasploit-framework$ ./msfconsole -q -x "load test_env; exit"
[*] VulnEnv plugin loaded.
[*] Successfully loaded plugin: vulnenv

nayera@Nero:~/git/metasploit-framework$ ./msfconsole -q -x "load test_env; test_env help; exit"
[*] VulnEnv plugin loaded.
[*] Successfully loaded plugin: vulnenv
Usage: test_env <command>

Commands:
build Build and launch environment for active module
list List tracked environments
stop <ID> Stop a running environment
start <ID> Restart a stopped environment
remove <ID> Tear down an environment
remove-all Tear down all environments
exec <ID> Execute exploit against environment
help Show this help
```

## Data Files

- [data/vuln_envs/jenkins.ym](https://github.com/Nayeraneru/metasploit-framework/blob/vulnenv-week1/data/vuln_envs/jenkins.yml) — Reference environment definition (Week 1 draft)
Empty file.
Loading
Loading