Back to Cheat Sheets

โš™๏ธ Security Misconfiguration2025

OWASP Web Top 10 2025 ยท A02

HIGH RISK

๐Ÿ“‹ What Is It?

Security Misconfiguration arises when an application, or any layer it depends on, ships with insecure settings: unsafe defaults, security controls never switched on, overly broad permissions, sample or admin components left installed, or verbose behaviour that leaks internal detail. It is not one bug in your code โ€” it is the accumulated gap between how a system can be hardened and how it was actually deployed.

A02 OWASP Rank
Defaults Root Cause
Easy To Prevent

โš ๏ธ Common Attack Vectors

  • Fingerprinting via banners & headers (Server, X-Powered-By)
  • Default / sample credentials (admin/admin)
  • Verbose errors & debug console (leads to RCE)
  • Directory listing & exposed .git / .env / backups
  • Overly permissive CORS (reflected Origin + credentials)
  • XXE and unpatched / outdated components

๐Ÿ”ด Attack Flow

1. Fingerprint: banner reveals a debug build
โ†“
2. Trigger error: stack trace confirms debug on
โ†“
3. Interactive console executes code as www-data
โ†“
4. Console reads .env, yielding cloud IAM keys
โ†“
5. IMPACT: pivot to cloud, drain buckets!

โŒ Vulnerable Code

from flask import Flask app = Flask(__name__) if __name__ == "__main__": # debug=True in prod -> interactive console = RCE app.run(host="0.0.0.0", port=5000, debug=True)

โœ… Secure Code

import os from flask import Flask, jsonify app = Flask(__name__) app.config["SECRET_KEY"] = os.environ["APP_SECRET_KEY"] app.config["DEBUG"] = False @app.errorhandler(500) def server_error(e): app.logger.exception(e) # detail to logs return jsonify(error="Internal Server Error"), 500 # Run behind gunicorn/uwsgi, never the dev server

โœ“ Prevention Checklist

  • Start from a hardened CIS/STIG baseline in IaC
  • Remove unused modules, ports, sample apps
  • Change all default credentials; use a secrets manager
  • Debug off; generic client errors; detail in logs only
  • Set HSTS, CSP, nosniff, Referrer-Policy on every response
  • Disable directory listing; keep .git / .env unreachable
  • Explicit CORS allow-list; never reflected origin + creds
  • Disable DTDs / external entities in XML parsers
  • Segment tiers; least privilege; isolate management plane
  • Verify config, headers & TLS continuously in CI

๐ŸŒ Real-World & Pitfalls

The former XXE category (A4:2017) is merged here โ€” always disable DTDs and external entities in XML parsers.

Common pitfall: Leaving debug=True on a production Flask/Django app exposes an interactive console that is direct remote code execution. Ship with debug off and run behind a real WSGI server.

๐Ÿ” Tools & Takeaway

nuclei nikto feroxbuster Shodan Trivy testssl.sh
Key Takeaway: Defaults are chosen to make software start, not to make it safe. Start from a hardened baseline, codify it so every environment is identical, and verify continuously โ€” an untested baseline drifts back to insecure.