Enterprise-Grade Web Application Security Training Platform
Self-hosted vulnerable web application platform with 40+ exploitable labs mapped to OWASP Top 10, CWE/SANS Top 25, and real-world HackerOne disclosures. Designed for penetration testers, security researchers, and developers building secure applications.
- Quick Start
- System Requirements
- Installation
- Platform Architecture
- Vulnerability Categories
- Lab Catalog
- Progress Tracking System
- Database Configuration API
- Exploitation Methodology
- Attack Surface Mapping
- Toolchain Integration
- Development Guide
- Troubleshooting
- Security Considerations
- References
# 1. Clone
git clone https://github.com/M9nx/LABx_Docs.git
cd LABx_Docs
# 2. Deploy to web root
# Windows: move to C:\xampp\htdocs\
# Linux: sudo mv to /var/www/html/
# 3. Start services (Apache + MySQL)
# 4. Access http://localhost/LABx_Docs/
# 5. Configure database credentials via UI
# 6. Initialize databases: Sidebar > Setup Databases > Setup All
# 7. Begin exploitation| Component | Requirement | Verification |
|---|---|---|
| PHP | 8.0.0+ | php -v |
| MySQL | 5.7.0+ | mysql --version |
| Apache | 2.4.0+ | httpd -v or apache2 -v |
| Memory | 512MB RAM | - |
| Storage | 100MB | - |
# Verify extensions
php -m | grep -E "mysqli|json|session|mbstring"
# Required
ext-mysqli # MySQL database connectivity
ext-json # JSON encode/decode operations
ext-session # Session management
ext-mbstring # Multibyte string handling (recommended); php.ini recommended settings
session.cookie_httponly = 1
session.use_strict_mode = 1
display_errors = On ; For lab debugging
error_reporting = E_ALL| Environment | Version | Status |
|---|---|---|
| XAMPP Windows | 8.2.12 | Verified |
| XAMPP Linux | 8.2.4 | Verified |
| WAMP | 3.3.0 | Verified |
| MAMP | 6.8 | Verified |
| Docker php:8.2-apache | Latest | Verified |
| Ubuntu 22.04 + LAMP | Native | Verified |
git clone https://github.com/M9nx/LABx_Docs.gitcurl -L https://github.com/M9nx/LABx_Docs/archive/main.zip -o LABx_Docs.zip
unzip LABx_Docs.zip
mv LABx_Docs-main LABx_Docs# docker-compose.yml
version: '3.8'
services:
web:
image: php:8.2-apache
ports:
- "8080:80"
volumes:
- ./LABx_Docs:/var/www/html/LABx_Docs
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
ports:
- "3306:3306"docker-compose up -d
# Access: http://localhost:8080/LABx_Docs/
# DB Host: db (Docker service name)-
Verify file permissions
# Linux/macOS chmod -R 755 LABx_Docs/ chown -R www-data:www-data LABx_Docs/ -
Configure database credentials
- Navigate to
http://localhost/LABx_Docs/ - Enter MySQL host, username, password
- Click "Test & Save"
- Navigate to
-
Initialize lab databases
- Sidebar > Setup Databases
- Click "Setup All" or initialize individually
-
Verify installation
- Access any lab (e.g., AC/Lab-01)
- Complete the lab
- Verify progress tracking
LABx_Docs/
│
├── index.php # Main dashboard, DB configuration UI
├── db-config.php # Centralized credential management API
├── index.md # Markdown index
├── README.md # This documentation
│
├── src/ # Shared platform components
│ ├── sidebar.php # Global navigation sidebar
│ ├── sidebar.css # Sidebar stylesheet
│ ├── setup.php # Database initialization wizard
│ └── progress.php # Cross-category progress aggregator
│
├── AC/ # Access Control category
│ ├── index.php # Category dashboard
│ ├── progress.php # AC progress helper (ac_progress DB)
│ ├── PROGRESS_TRACKING.md # Progress system documentation
│ ├── setup-all-databases.php # Batch database setup
│ └── Lab-01/ ... Lab-30/ # 30 individual lab directories
│
├── Insecure-Deserialization/ # Deserialization category
│ ├── index.php # Category dashboard
│ ├── progress.php # ID progress helper (id_progress DB)
│ ├── PROGRESS_TRACKING.md
│ └── Lab-01/ ... Lab-10/ # 10 individual lab directories
│
├── API/ # API Security category (planned)
│ ├── index.php
│ ├── progress.php # api_progress DB
│ └── PROGRESS_TRACKING.md
│
└── Authentication/ # Authentication category (planned)
├── index.php
├── progress.php # auth_progress DB
└── PROGRESS_TRACKING.md
Each lab follows a standardized structure:
Lab-XX/
│
├── index.php # Lab entry point, scenario UI
├── lab-description.php # Challenge objectives, attack hints
├── docs.php # Technical documentation, walkthrough
│
├── config.php # Database connection configuration
├── setup_db.php # Database initialization script
├── database_setup.sql # SQL schema, seed data, test accounts
│
├── login.php # Authentication endpoint (if applicable)
├── logout.php # Session termination
├── [vulnerable-endpoint].php # Exploitable functionality
│
├── success.php # Completion verification, flag display
├── LAB_DOCUMENTATION.md # Comprehensive markdown documentation
└── README.md # Lab-specific README
┌─────────────────────────────────────────────────────────────────┐
│ index.php │
│ (Main Dashboard + DB Config) │
└───────────────────────────┬─────────────────────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ db-config.php │ │ src/sidebar.php │
│ (Credential Storage) │ │ (Global Navigation) │
└─────────────────────────┘ └─────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Category Dashboards │
│ AC/index.php | ID/index.php | API/index.php │
└───────────────────────────┬─────────────────────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ Lab-XX/index.php │ │ [category]/progress.php│
│ (Lab Scenario) │ │ (Progress Tracking) │
└───────────────────────────┘ └─────────────────────────┘
│
▼
┌─────────────────────────┐
│ Lab-XX/success.php │
│ (Completion Handler) │
└─────────────────────────┘
| Category | Labs | OWASP 2021 | CWE ID | Difficulty Range |
|---|---|---|---|---|
| Access Control | 30 | A01:2021 | CWE-284, CWE-639, CWE-862 | Apprentice - Expert |
| Insecure Deserialization | 10 | A08:2021 | CWE-502 | Apprentice - Expert |
| API Security | TBD | A01, A02, A03 | CWE-284, CWE-287, CWE-200 | Planned |
| Authentication | TBD | A07:2021 | CWE-287, CWE-307, CWE-384 | Planned |
| OWASP 2021 | Category | Labs |
|---|---|---|
| A01: Broken Access Control | Access Control | 30 |
| A02: Cryptographic Failures | - | - |
| A03: Injection | - | - |
| A04: Insecure Design | - | - |
| A05: Security Misconfiguration | - | - |
| A06: Vulnerable Components | - | - |
| A07: Auth Failures | Authentication | TBD |
| A08: Data Integrity Failures | Insecure Deserialization | 10 |
| A09: Logging Failures | - | - |
| A10: SSRF | - | - |
| # | Title | Difficulty | CWE | Attack Vector |
|---|---|---|---|---|
| 01 | Unprotected Admin Functionality | Apprentice | CWE-425 | robots.txt disclosure |
| 02 | Unpredictable Admin URL | Apprentice | CWE-425 | JavaScript source analysis |
| 03 | User Role Manipulation | Apprentice | CWE-639 | Cookie parameter tampering |
| 04 | IDOR Account Takeover | Practitioner | CWE-639 | Direct object reference |
| 05 | User ID via Request Parameter | Practitioner | CWE-639 | GET/POST parameter manipulation |
| 06 | Unpredictable User IDs | Practitioner | CWE-639 | GUID enumeration |
| 07 | Data Leakage in Redirect | Practitioner | CWE-639 | Response body before redirect |
| 08 | Password Disclosure | Practitioner | CWE-639 | Source code exposure |
| 09 | Classic IDOR | Practitioner | CWE-639 | Sequential ID enumeration |
| 10 | URL-Based Access Control Bypass | Practitioner | CWE-284 | X-Original-URL header injection |
| 11 | Method-Based Access Control | Practitioner | CWE-284 | HTTP method override |
| 12 | Multi-Step Process Bypass | Practitioner | CWE-284 | Workflow state manipulation |
| 13 | Referer-Based Access Control | Practitioner | CWE-284 | Referer header spoofing |
| 14 | Mass Assignment IDOR | Practitioner | CWE-915 | Object property injection |
| 15 | Email Change IDOR | Practitioner | CWE-639 | Account takeover via email |
| 16 | Sequential ID Enumeration | Practitioner | CWE-639 | Predictable identifier |
| 17 | Horizontal Privilege Escalation | Practitioner | CWE-639 | Cross-user data access |
| 18 | Parameter Pollution IDOR | Practitioner | CWE-639 | HTTP parameter pollution |
| 19 | API Endpoint IDOR | Practitioner | CWE-639 | REST API object reference |
| 20 | Encoded/Hashed ID IDOR | Practitioner | CWE-639 | Base64/hash decoding |
| 21 | JWT Token Manipulation | Practitioner | CWE-639 | JWT claim modification |
| 22 | Indirect Object Reference | Practitioner | CWE-639 | Indirect reference map bypass |
| 23 | Role Parameter Escalation | Practitioner | CWE-269 | Role field injection |
| 24 | Vertical Privilege Escalation | Practitioner | CWE-269 | Admin function access |
| 25 | File Upload Access Control | Practitioner | CWE-639 | File reference manipulation |
| 26 | Path Traversal Bypass | Practitioner | CWE-22 | Directory traversal + IDOR |
| 27 | HackerOne: PII Disclosure | Practitioner | CWE-639 | Real-world case study |
| 28 | HackerOne: Account Deletion | Practitioner | CWE-639 | Real-world case study |
| 29 | HackerOne: Mass Assignment | Practitioner | CWE-915 | Real-world case study |
| 30 | GraphQL Mutation IDOR | Expert | CWE-639 | GraphQL parameter manipulation |
Difficulty Distribution: Apprentice (3) | Practitioner (26) | Expert (1)
| # | Title | Difficulty | CWE | Attack Vector |
|---|---|---|---|---|
| 01 | Modifying Serialized Objects | Apprentice | CWE-502 | Cookie base64 tampering |
| 02 | Serialized Data Types | Apprentice | CWE-502 | PHP type juggling |
| 03 | Application Functionality Abuse | Practitioner | CWE-502 | Serialized method invocation |
| 04 | Arbitrary Object Injection | Practitioner | CWE-502 | Magic method exploitation |
| 05 | Pre-Built Gadget Chain (PHP) | Practitioner | CWE-502 | Known gadget chain |
| 06 | Documented Gadget Chain (Ruby) | Practitioner | CWE-502 | Framework gadget chain |
| 07 | Custom Gadget Chain (PHP) | Expert | CWE-502 | Custom gadget construction |
| 08 | Custom Gadget Chain (Java) | Expert | CWE-502 | Java deserialization |
| 09 | PHAR Deserialization | Expert | CWE-502 | PHAR polyglot upload |
| 10 | Cookie-Based Deserialization | Apprentice | CWE-502 | Session cookie tampering |
Difficulty Distribution: Apprentice (3) | Practitioner (4) | Expert (3)
Each category maintains an isolated progress database:
| Category | Database Name | Connection |
|---|---|---|
| Access Control | ac_progress |
AC/progress.php |
| Insecure Deserialization | id_progress |
Insecure-Deserialization/progress.php |
| API Security | api_progress |
API/progress.php |
| Authentication | auth_progress |
Authentication/progress.php |
CREATE DATABASE IF NOT EXISTS ac_progress;
USE ac_progress;
CREATE TABLE IF NOT EXISTS solved_labs (
id INT PRIMARY KEY AUTO_INCREMENT,
lab_number INT NOT NULL UNIQUE,
solved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_lab_number (lab_number)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;<?php
// Located at: [Category]/progress.php
/**
* Check if a specific lab is solved
* @param int $labNumber Lab number (1-30 for AC, 1-10 for ID)
* @return bool True if solved, false otherwise
*/
function isLabSolved(int $labNumber): bool;
/**
* Mark a lab as solved (idempotent)
* @param int $labNumber Lab number to mark
* @return bool True on success
*/
function markLabSolved(int $labNumber): bool;
/**
* Get all solved lab numbers
* @return array Array of solved lab numbers
*/
function getSolvedLabs(): array;
/**
* Get total count of solved labs
* @return int Number of solved labs
*/
function getSolvedCount(): int;
/**
* Reset a lab's solved status
* @param int $labNumber Lab to reset
* @return bool True on success
*/
function resetLab(int $labNumber): bool;<?php
// Lab success.php implementation
require_once('../progress.php');
// Verify completion condition (lab-specific logic)
$isComplete = verifyLabCompletion();
if ($isComplete) {
markLabSolved(5); // Mark Lab 05 as complete
// Display success message
echo "Lab completed!";
echo "Flag: FLAG{lab_05_solved}";
}
// Check if already solved
if (isLabSolved(5)) {
echo "You have already completed this lab.";
}POST /LABx_Docs/db-config.php
POST /LABx_Docs/db-config.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=test&host=localhost&user=root&pass=Response:
{
"success": true,
"message": "Connection successful"
}POST /LABx_Docs/db-config.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=statusResponse:
{
"configured": true,
"host": "localhost",
"user": "root"
}POST /LABx_Docs/db-config.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=clearResponse:
{
"success": true,
"message": "Credentials cleared"
}<?php
require_once '/path/to/LABx_Docs/db-config.php';
// Retrieve stored credentials
$credentials = getDbCredentials();
// Returns: ['host' => 'localhost', 'user' => 'root', 'pass' => '', 'configured' => true]
// Use credentials for database connection
$conn = new mysqli(
$credentials['host'],
$credentials['user'],
$credentials['pass'],
'lab_database'
);1. Read lab-description.php for objectives and hints
2. Explore application functionality
3. Identify entry points (forms, parameters, cookies, headers)
4. Analyze client-side source (JavaScript, HTML comments)
5. Check for information disclosure (robots.txt, .git, backups)
1. Map input vectors to potential vulnerability classes
2. Test for common flaws:
- IDOR: Modify ID parameters
- Access Control: Try unauthorized endpoints
- Deserialization: Analyze cookie structures
3. Use Burp Suite for request/response analysis
4. Check server responses for sensitive data leakage
1. Develop proof-of-concept exploit
2. Achieve lab objective:
- Delete target user
- Access unauthorized data
- Escalate privileges
- Retrieve flag
3. Navigate to success.php for verification
1. Document exploitation steps
2. Identify root cause
3. Propose remediation
4. Review docs.php for official walkthrough
| Entry Point | Attack Vectors | Tools |
|---|---|---|
| URL Parameters | IDOR, SQLi, XSS, Path Traversal | Burp Repeater, curl |
| POST Body | Mass Assignment, IDOR, CSRF | Burp Repeater, Postman |
| Cookies | Deserialization, Session Hijacking | Browser DevTools, Burp |
| HTTP Headers | X-Original-URL, X-Forwarded-For, Referer | curl, Burp Intruder |
| File Uploads | Path Traversal, RCE, IDOR | Burp, custom scripts |
| GraphQL | IDOR via mutations, Introspection | GraphQL Playground, Altair |
# Enumerate sequential IDs
for i in {1..100}; do
curl -s "http://localhost/Lab-05/profile.php?id=$i" | grep -q "secret" && echo "Found: $i"
done
# Test encoded IDs
echo -n "2" | base64
# Mg==
curl "http://localhost/Lab-20/profile.php?id=Mg=="// Generate malicious serialized object
$payload = 'O:8:"stdClass":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:1;}';
$encoded = base64_encode($payload);
echo $encoded;
// Tzo4OiJzdGRDbGFzcyI6Mjp7czo4OiJ1c2VybmFtZSI7czo2OiJ3aWVuZXIiO3M6NToiYWRtaW4iO2I6MTt9# X-Original-URL bypass
curl -H "X-Original-URL: /admin" http://localhost/Lab-10/
# HTTP method override
curl -X POST -d "_method=DELETE" http://localhost/Lab-11/user/1
# Referer manipulation
curl -H "Referer: http://localhost/admin" http://localhost/Lab-13/admin-action1. Configure browser proxy: 127.0.0.1:8080
2. Add LABx_Docs to scope: http://localhost/LABx_Docs/*
3. Disable interception for static files (*.css, *.js, *.png)
4. Use Repeater for parameter manipulation
5. Use Intruder for ID enumeration
Application Tab:
- Cookies: View/modify session cookies
- Local Storage: Check for sensitive data
Network Tab:
- Monitor requests/responses
- Replay requests with modifications
Console:
- Execute JavaScript for dynamic analysis
- Decode base64: atob("encodedstring")
# curl for quick testing
curl -c cookies.txt -b cookies.txt \
-X POST -d "username=wiener&password=peter" \
http://localhost/LABx_Docs/AC/Lab-01/login.php
# httpie for readable output
http POST localhost/LABx_Docs/AC/Lab-05/profile.php id=2 Cookie:session=abc123
# jq for JSON parsing
curl -s http://localhost/api/user/1 | jq '.data.email'#!/usr/bin/env python3
"""IDOR enumeration script"""
import requests
session = requests.Session()
session.post('http://localhost/LABx_Docs/AC/Lab-05/login.php',
data={'username': 'wiener', 'password': 'peter'})
for user_id in range(1, 100):
resp = session.get(f'http://localhost/LABx_Docs/AC/Lab-05/profile.php?id={user_id}')
if 'admin' in resp.text.lower():
print(f'[+] Admin found: ID {user_id}')
print(resp.text)
breakmkdir -p AC/Lab-31
cd AC/Lab-31touch index.php # Entry point
touch lab-description.php # Challenge description
touch docs.php # Technical walkthrough
touch config.php # Database config
touch setup_db.php # DB initialization
touch database_setup.sql # SQL schema
touch login.php # Auth (if needed)
touch logout.php # Session cleanup
touch success.php # Completion handler
touch README.md # Lab documentation<?php
// config.php
require_once('../../db-config.php');
$creds = getDbCredentials();
$host = $creds['host'];
$user = $creds['user'];
$pass = $creds['pass'];
$dbname = 'ac_lab31';
$conn = new mysqli($host, $user, $pass, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}<?php
// success.php
require_once('../progress.php');
session_start();
// Lab-specific completion logic
$completed = isset($_GET['deleted']) && $_GET['deleted'] === 'carlos';
if ($completed) {
markLabSolved(31);
}
?>
<!DOCTYPE html>
<html>
<head><title>Lab 31 - Success</title></head>
<body>
<?php if ($completed): ?>
<h1>Congratulations!</h1>
<p>You have successfully completed Lab 31.</p>
<code>FLAG{ac_lab31_completed}</code>
<?php else: ?>
<h1>Not Complete</h1>
<p>Complete the lab objective to see the flag.</p>
<?php endif; ?>
</body>
</html>Update src/setup.php to include the new lab in the setup wizard.
| Issue | Cause | Solution |
|---|---|---|
| "Connection failed" | Invalid credentials | Verify MySQL host/user/pass on dashboard |
| "Database not found" | Lab not initialized | Run Setup Databases from sidebar |
| PHP errors displayed | Debug mode enabled | Expected in development environment |
| Blank page | PHP fatal error | Check Apache error log |
| Session lost | Cookie issues | Clear browser cookies, restart |
# XAMPP Windows
C:\xampp\apache\logs\error.log
C:\xampp\mysql\data\*.err
# Linux Apache
/var/log/apache2/error.log
/var/log/mysql/error.log
# PHP
# Check phpinfo() for error_log path# Test MySQL connection
mysql -h localhost -u root -p -e "SHOW DATABASES;"
# Test PHP
php -r "phpinfo();" | grep mysqli
# Check Apache config
apachectl configtest
# Verify file permissions
ls -la /var/www/html/LABx_Docs/| Environment | Allowed |
|---|---|
| localhost | Yes |
| LAN (isolated) | Yes - with firewall |
| VPN/Private | Yes - authenticated |
| Public Internet | NO |
| Production Server | NO |
| Cloud VPS (public IP) | NO |
1. Run only on isolated development machines
2. Use host-only networking for VMs
3. Block external access via firewall
4. Never expose to internet
5. Do not store real credentials or data
- Security training and education
- Penetration testing practice
- Secure coding demonstrations
- CTF preparation
- Security certification study (OSCP, CEH, CompTIA Security+)
| CWE | Name | Category |
|---|---|---|
| CWE-284 | Improper Access Control | Access Control |
| CWE-639 | Insecure Direct Object Reference | Access Control |
| CWE-862 | Missing Authorization | Access Control |
| CWE-269 | Improper Privilege Management | Access Control |
| CWE-915 | Mass Assignment | Access Control |
| CWE-502 | Deserialization of Untrusted Data | Deserialization |
| CWE-22 | Path Traversal | Access Control |
| CWE-425 | Direct Request (Forced Browsing) | Access Control |
Educational use only. Not intended for production deployment.
- Fork repository
- Create feature branch:
git checkout -b feature/lab-name - Follow lab structure conventions
- Include documentation (README.md, LAB_DOCUMENTATION.md)
- Submit pull request
Issue Reports: GitHub Issues
LABx_Docs v2.0 | 40+ Labs | 4 Categories | OWASP Top 10 Coverage