The XSS Rat OWASP Lab by The XSS Rat
A02:2025 High

Security Misconfiguration

Theory

Security Misconfiguration rose from #5 in 2021 to #2 in 2025: 100% of applications tested were found to have some form of misconfiguration, across more than 719,000 recorded occurrences. The 2025 edition attributes the jump to the shift toward highly configurable software, where every knob is a chance to get it wrong. It encompasses every case where a system is set up insecurely: wrong defaults left in place, unnecessary features enabled, overly permissive permissions, or missing security headers. The defining characteristic: the vulnerability is in how the software is deployed or configured, not in the code itself.

Types of Security Misconfiguration

  • Debug endpoints in production — /debug, /_debug/toolbar, /actuator/env endpoints that expose env vars, secrets, and stack traces
  • Default credentials — admin:admin, admin:password on databases (MySQL root with no password), admin panels (Jenkins, Tomcat, Elasticsearch)
  • Verbose error messages — full stack traces returned to the browser leak framework versions, file paths, database structure, and internal logic
  • Open cloud storage — S3 buckets, Azure Blob storage, or GCS buckets with public read access containing sensitive files
  • Missing security headers — no Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, or Strict-Transport-Security
  • Unnecessary services exposed — Redis, MongoDB, Memcached, or Elasticsearch directly accessible from the internet with no authentication
  • XML External Entity (XXE) enabled — XML parsers configured to resolve external entities by default

Debug Endpoint — Vulnerable Code

# VULNERABLE — debug route left in production with no auth guard
@app.get("/debug")
def debug_info():
    return {
        "env": dict(os.environ),           # leaks SECRET_KEY, DB_PASSWORD, API_KEYS...
        "config": app.state.config,        # internal config values
        "database_url": settings.DB_URL,   # full connection string with credentials
    }

# This is what Spring Boot Actuator exposes by default:
# GET /actuator/env  →  all environment variables
# GET /actuator/heapdump  →  full JVM heap dump (extract credentials from memory)
# GET /actuator/mappings  →  all route mappings (attack surface map)

Fixed Code

# FIXED — debug endpoint only exists in non-production environments
import os

if os.getenv("ENVIRONMENT") != "production":
    @app.get("/debug")
    def debug_info():
        # Even in dev, never expose raw env vars
        return {"status": "debug mode", "version": app.version}

# For frameworks with built-in debug features:
# Flask:  app.run(debug=False)  in production
# Django: DEBUG = False  in settings.py for production
# Spring: management.endpoints.web.exposure.exclude=*  in application.properties

Missing Security Headers — Vulnerable vs Fixed

# VULNERABLE — no security headers; browser has no protection hints
# Response headers:
Content-Type: text/html

# FIXED — add security headers middleware
from fastapi.middleware import Middleware

@app.middleware("http")
async def add_security_headers(request, call_next):
    response = await call_next(request)
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["X-Frame-Options"] = "DENY"
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
    response.headers["Permissions-Policy"] = "geolocation=(), camera=()"
    return response

Real-World Breaches

  • Capital One (2019) — An EC2 instance had an overly permissive IAM role + SSRF vulnerability. The misconfigured role allowed reading 100M customer records from S3. $80M fine.
  • Elasticsearch incidents (ongoing) — Thousands of databases left internet-facing with no authentication. Multiple breaches of millions of records each year
  • GrayShift (2018) — An internal web panel had no password protection; source code and pricing leaked
  • Microsoft Power Apps (2021) — Default portal configuration made data public; 38 million records (COVID vaccination status, SSNs) were exposed across 47 organisations

How to Fix — Checklist

  • Harden defaults — disable everything you don't need; enable only what you do. Run CIS Benchmark hardening guides for your OS, DB, and cloud provider
  • Change all default credentials — automate this in your provisioning scripts (Terraform, Ansible). Fail CI if default creds are detected
  • Remove debug features from production builds — use build flags or environment checks; never ship debug=True to prod
  • Security headers — use securityheaders.com to audit and implement all recommended headers
  • Scan with tools — OWASP ZAP, Nuclei, AWS Config, Scout Suite for cloud; integrate into CI/CD pipeline
  • Principle of least privilege — every service, container, and cloud role should have only the permissions it needs and nothing more
Challenge 1

Debug Endpoint Exposes Sensitive Data

A debug endpoint was left enabled in production and exposes environment variables, config values, and secrets.

Steps
Visit /web/a02/debug directly.
Challenge 2

Default Credentials

The management panel uses default credentials that were never changed.

Steps
Try username admin, password admin.