Skip to main content
Career Paths
Concepts
Owasp Top 10
The Simplified Tech

Role-based learning paths to help you master cloud engineering with clarity and confidence.

Product

  • Career Paths
  • Interview Prep
  • Scenarios
  • AI Features
  • Cloud Comparison
  • Resume Builder
  • Pricing

Community

  • Join Discord

Account

  • Dashboard
  • Credits
  • Updates
  • Sign in
  • Sign up
  • Contact Support

Stay updated

Get the latest learning tips and updates. No spam, ever.

Terms of ServicePrivacy Policy

© 2026 TheSimplifiedTech. All rights reserved.

BackBack
Interactive Explainer

OWASP Top 10

The ten most critical web application security risks — SQL injection, XSS, broken access control, cryptographic failures, and more — with real-world examples and prevention patterns every engineer must know.

🎯Key Takeaways
A01 Broken Access Control is the #1 risk — deny by default, check ownership at query level, test with unprivileged accounts.
A02 Cryptographic Failures — use TLS everywhere, Argon2id for passwords, never MD5/SHA1 for passwords, never roll your own crypto.
A03 Injection — use parameterised queries / ORMs, never interpolate user input into SQL/shell commands.
A06 Vulnerable Components — use SCA scanning (Snyk/Dependabot) and enforce patch SLAs.
A07 Auth Failures — enforce MFA, secure session management, protect against credential stuffing.
A09 Logging Failures — log authentication events, access failures, admin actions; alert on anomalies; never log credentials.
A10 SSRF — validate and allowlist URLs, block IMDS access, disable redirects, use IMDSv2.
The OWASP Top 10 is the minimum security knowledge baseline for every engineer writing web application code.

OWASP Top 10

The ten most critical web application security risks — SQL injection, XSS, broken access control, cryptographic failures, and more — with real-world examples and prevention patterns every engineer must know.

~9 min read
Be the first to complete!
Why this matters

Most web application breaches exploit a small set of well-understood, preventable vulnerability classes. Developers who do not know these vulnerabilities write code that contains them.

Without this knowledge

SQL injection, XSS, broken access control, and insecure deserialization are found in production applications every day — often years after they were introduced. These are not exotic vulnerabilities; they are standard bugs that should never ship.

With this knowledge

Every engineer on your team understands the top vulnerability patterns, recognises insecure code in review, and knows which framework features prevent each class. Security becomes part of the development instinct, not a separate audit.

What you'll learn
  • A01 Broken Access Control is the #1 risk — deny by default, check ownership at query level, test with unprivileged accounts.
  • A02 Cryptographic Failures — use TLS everywhere, Argon2id for passwords, never MD5/SHA1 for passwords, never roll your own crypto.
  • A03 Injection — use parameterised queries / ORMs, never interpolate user input into SQL/shell commands.
  • A06 Vulnerable Components — use SCA scanning (Snyk/Dependabot) and enforce patch SLAs.
  • A07 Auth Failures — enforce MFA, secure session management, protect against credential stuffing.
  • A09 Logging Failures — log authentication events, access failures, admin actions; alert on anomalies; never log credentials.
  • A10 SSRF — validate and allowlist URLs, block IMDS access, disable redirects, use IMDSv2.
  • The OWASP Top 10 is the minimum security knowledge baseline for every engineer writing web application code.

Lesson outline

OWASP Top 10 (2021) — Overview

OWASP (Open Web Application Security Project) publishes the Top 10 most critical web application security risks every 3–4 years, based on data from thousands of organisations and security researchers.

RankVulnerabilityKey RiskPrevention
A01Broken Access Control94% of applications tested had some form of broken access controlDeny by default; enforce on server; test with unprivileged accounts
A02Cryptographic FailuresData exposed in transit or at rest due to weak/missing encryptionTLS everywhere; strong algorithms; never roll your own crypto
A03Injection (SQL, LDAP, OS, NoSQL)Untrusted data sent to an interpreterParameterised queries; ORM; input validation; allowlists
A04Insecure DesignMissing security controls at design phase; no threat modellingThreat modelling; secure design patterns; security requirements
A05Security MisconfigurationUnnecessary features enabled; default passwords; verbose errorsHardening guides; automated config scanning; minimal surface area
A06Vulnerable and Outdated ComponentsUsing dependencies with known CVEsSCA scanning; automated updates; SBOM
A07Identification and Authentication FailuresWeak passwords; no MFA; session management flawsMFA; secure session handling; credential stuffing protection
A08Software and Data Integrity FailuresUnsigned updates; deserialization of untrusted data; CI/CD integritySign artifacts; verify checksums; avoid unsafe deserialization
A09Security Logging and Monitoring FailuresBreaches not detected due to missing logs or alertsLog security events; alert on anomalies; test detection coverage
A10Server-Side Request Forgery (SSRF)Server fetches attacker-controlled URL, accessing internal servicesValidate and allowlist URLs; disable redirects; block IMDS
Aha!

A01 — Broken Access Control: The #1 Risk

Broken access control moved to #1 in 2021. It means users can act outside their intended permissions — accessing other users' data, calling admin functions, or modifying access controls.

Common broken access control patterns

  • IDOR (Insecure Direct Object Reference) — Changing an ID in a URL/request accesses another user's data — the same as BOLA in API security
  • Force browsing — Directly accessing /admin, /backup, /config that should require elevated roles
  • Missing function-level access control — DELETE /api/users/:id works for regular users even though only admins should delete users
  • CORS misconfiguration — API allows requests from any origin (Access-Control-Allow-Origin: *) — allows cross-site request forgery from malicious sites
  • Privilege escalation via JWT tampering — JWT signed with "none" algorithm or weak secret — attacker modifies role claim

Deny by default — explicitly grant, never assume

Every endpoint and resource should deny access by default. Access is granted explicitly via role checks or ownership checks. Test access control by running your test suite with unprivileged accounts and verifying that restricted operations return 403/404.

sql-injection-prevention.py
1# A03: SQL Injection — vulnerable vs safe (Python / SQLAlchemy)
2
3# ❌ VULNERABLE — string interpolation in SQL
VULNERABLE — f-string or + concatenation in SQL is always wrong
4def get_user_by_name(username: str):
5 query = f"SELECT * FROM users WHERE username = '{username}'"
6 # Attacker sends: username = "admin' OR '1'='1"
7 # Query becomes: SELECT * FROM users WHERE username = 'admin' OR '1'='1'
8 # Returns all users!
9 return db.execute(query).fetchall()
10
11# ❌ ALSO VULNERABLE — string formatting
12def search_products(category: str):
13 return db.execute(
14 "SELECT * FROM products WHERE category = '" + category + "'"
15 ).fetchall()
16
17# ✅ SAFE — parameterised query (positional placeholder)
SAFE — ? placeholder; driver handles escaping
18def get_user_by_name_safe(username: str):
19 return db.execute(
20 "SELECT * FROM users WHERE username = ?",
21 (username,) # Driver escapes the value — injection impossible
22 ).fetchall()
ORM uses parameterised queries automatically
23
24# ✅ SAFE — ORM with parameterised queries under the hood
25def get_user_by_name_orm(username: str):
26 return User.query.filter_by(username=username).first()
27
28# ✅ SAFE — SQLAlchemy text() with bound parameters
29from sqlalchemy import text
30def search_safe(category: str, min_price: float):
31 return db.execute(
32 text("SELECT * FROM products WHERE category = :cat AND price >= :price"),
33 {"cat": category, "price": min_price}
34 ).fetchall()
35
36# BONUS: stored procedure input validation
37import re
38def validate_username(username: str) -> bool:
39 return bool(re.match(r'^[a-zA-Z0-9_]{3,50}$', username))

A03 — Injection: SQL, NoSQL, Command, LDAP

Injection occurs when untrusted data is sent to an interpreter as part of a command or query. The interpreter cannot distinguish data from instructions.

Injection TypeExample SinkPrevention
SQLdb.query("SELECT ... WHERE id = " + userId)Parameterised queries, ORM
NoSQLdb.users.find({ username: req.body.username })Schema validation, $where avoidance, allowlisted operators
OS Commandexec("ping " + userInput)Avoid shell execution; use language APIs; allowlist args
LDAPldap.search("(uid=" + username + ")")Escape special chars: ( ) * \ NUL / @ = < >
XPathxpath.select("//user[name=" + input + "]")Parameterised XPath queries
Template injection (SSTI)template.render(userInput)Never pass user input as template string; use context only
Log injectionlogger.info("User: " + username)Sanitise log entries; encode newlines; structured logging

NoSQL injection is real and commonly overlooked

MongoDB queries accept operators like $where, $gt, $ne. If user input is inserted directly into a query object — db.users.find({username: req.body.username, password: req.body.password}) — an attacker can send {"username": "admin", "password": {"$ne": null}} to bypass password checking. Use schema validation (Joi/Zod) and avoid $where.

A02 — Cryptographic Failures

Cryptographic failures cover data exposed due to missing encryption, weak algorithms, improper key management, or cleartext transmission.

Common cryptographic failures

  • HTTP instead of HTTPS — Data in transit is visible to network observers. Use HTTPS everywhere, HSTS with preloading.
  • MD5 or SHA1 for password hashing — Reversible via rainbow tables and GPU cracking. Use bcrypt, scrypt, or Argon2 with work factor.
  • Storing passwords in plaintext or reversible encryption — Any breach immediately exposes all passwords. Always use one-way hashing.
  • Weak TLS configuration — TLS 1.0/1.1, RC4, DES, export ciphers. Require TLS 1.2+ with strong cipher suites.
  • Rolling your own crypto — Never implement cryptographic algorithms yourself. Use established libraries (libsodium, OpenSSL, AWS KMS).
  • Hardcoded or weak encryption keys — Keys must be randomly generated, stored in a secrets manager, and rotated.

Password hashing: Argon2id is the 2024 recommendation

Argon2id won the Password Hashing Competition and is the current OWASP recommendation. Bcrypt is acceptable for legacy systems. Never use MD5, SHA1, SHA256, or SHA512 for passwords — these are fast hashes designed for data integrity, not password security.

password-hashing.py
1# A07: Password hashing — wrong vs right
2
3# ❌ WRONG — MD5 (reversible via rainbow tables in seconds)
MD5 — cracked in milliseconds with GPU + rainbow tables
4import hashlib
5hashed = hashlib.md5(password.encode()).hexdigest()
6
7# ❌ WRONG — SHA256 (fast — GPU can try billions/sec)
8hashed = hashlib.sha256(password.encode()).hexdigest()
9
10# ❌ WRONG — plaintext storage (any DB breach = all passwords exposed)
11user.password = password
12
13# ✅ CORRECT — bcrypt (slow by design, includes salt)
bcrypt with rounds=12 — takes ~250ms deliberately (tunable)
14import bcrypt
15hashed = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=12))
16# Verify:
17bcrypt.checkpw(password.encode('utf-8'), hashed)
18
Argon2id — memory-hard, GPU-resistant, OWASP recommended
19# ✅ BEST — Argon2id (OWASP recommended, memory-hard)
20from argon2 import PasswordHasher
21ph = PasswordHasher(
22 time_cost=2, # Iterations
23 memory_cost=65536, # 64 MB
24 parallelism=2,
25 hash_len=32,
26 salt_len=16,
27)
28hashed = ph.hash(password)
29# Verify:
30ph.verify(hashed, password) # Raises VerifyMismatchError if wrong

A09 — Security Logging and Monitoring Failures

Without proper logging and monitoring, breaches go undetected for months. The median time to detect a breach is 207 days (IBM 2023). Logging failures mean you cannot detect, respond, or learn from attacks.

What to log for security

  • Authentication events — All login attempts (success and failure), MFA prompts, password resets, session creation and termination
  • Authorisation failures — Every 403/404 from an authenticated user — patterns indicate access control bypass attempts
  • Input validation failures — Rejected inputs (SQL injection patterns, XSS payloads, oversized payloads) indicate active probing
  • Administrative actions — User creation/deletion, role changes, configuration changes, data exports
  • High-value transactions — Payments, data exports, bulk operations — log before and after state
  • Rate limit breaches — Which account, which endpoint, what rate was hit — essential for abuse detection

Never log sensitive data

Passwords, credit card numbers, full SSNs, session tokens, and API keys must never appear in logs — even accidentally. Log that authentication occurred, not the credential used. Implement log scrubbing for known sensitive patterns. Treat logs as sensitive data requiring the same access controls as production data.

A10 — SSRF: Server-Side Request Forgery

SSRF allows an attacker to make the server issue HTTP requests to destinations they control — including internal services, cloud metadata endpoints, and localhost services not exposed externally.

AWS/GCP/Azure instance metadata is the primary SSRF target

The cloud instance metadata service (IMDS) at 169.254.169.254 (AWS/Azure) or 169.254.169.254/metadata.google.internal (GCP) provides IAM credentials, instance identity documents, and configuration data. An SSRF vulnerability can leak these credentials, giving an attacker full cloud API access. Capital One 2019 breach was caused by SSRF → IMDS credential theft.

SSRF prevention

→

01

Validate all user-supplied URLs against an allowlist of permitted domains and schemes

→

02

Block requests to private IP ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16

→

03

Disable redirects — an attacker can redirect from an allowed domain to an internal IP

→

04

Use IMDSv2 (AWS) which requires a PUT request with a session token before the GET — prevents simple SSRF credential theft

→

05

Run the fetching service with minimal network access (no internal network reachability)

06

Log all outbound HTTP requests made by your application

1

Validate all user-supplied URLs against an allowlist of permitted domains and schemes

2

Block requests to private IP ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16

3

Disable redirects — an attacker can redirect from an allowed domain to an internal IP

4

Use IMDSv2 (AWS) which requires a PUT request with a session token before the GET — prevents simple SSRF credential theft

5

Run the fetching service with minimal network access (no internal network reachability)

6

Log all outbound HTTP requests made by your application

How this might come up in interviews

OWASP Top 10 knowledge is tested in security-focused engineering interviews, secure code review assessments, and penetration testing interviews. Every backend engineer should be able to explain at least A01, A02, A03.

Common questions:

  • What is SQL injection and how do you prevent it?
  • Name 3 items from the OWASP Top 10 and explain them.
  • What is the difference between XSS and CSRF?
  • How would you prevent SSRF in an application that fetches URLs provided by users?
  • What is broken access control and how do you test for it?

Strong answer: Can explain BOLA/IDOR as A01, knows parameterised queries for A03, mentions Argon2 for A02 passwords, and understands SSRF impact on cloud metadata endpoints.

Red flags: Not knowing what SQL injection is, thinking HTTPS alone prevents all attacks, or confusing XSS with CSRF.

Quick check · OWASP Top 10

1 / 3

Which OWASP Top 10 vulnerability was the root cause of the Equifax 2017 breach?

Key takeaways

  • A01 Broken Access Control is the #1 risk — deny by default, check ownership at query level, test with unprivileged accounts.
  • A02 Cryptographic Failures — use TLS everywhere, Argon2id for passwords, never MD5/SHA1 for passwords, never roll your own crypto.
  • A03 Injection — use parameterised queries / ORMs, never interpolate user input into SQL/shell commands.
  • A06 Vulnerable Components — use SCA scanning (Snyk/Dependabot) and enforce patch SLAs.
  • A07 Auth Failures — enforce MFA, secure session management, protect against credential stuffing.
  • A09 Logging Failures — log authentication events, access failures, admin actions; alert on anomalies; never log credentials.
  • A10 SSRF — validate and allowlist URLs, block IMDS access, disable redirects, use IMDSv2.
  • The OWASP Top 10 is the minimum security knowledge baseline for every engineer writing web application code.
Before you move on: can you answer these?

What is the difference between stored XSS, reflected XSS, and DOM-based XSS?

Stored XSS: malicious script is saved in the database and served to every user who views the content (e.g., a comment field that stores <script>). Reflected XSS: malicious script is in the URL/request, reflected back in the response immediately without storage (e.g., a search page that echoes the search term unescaped). DOM-based XSS: the vulnerability is in client-side JavaScript that reads from the URL/localStorage and writes it to the DOM without sanitisation — the server never sees the payload. Prevention: output encoding for stored/reflected; use textContent not innerHTML for DOM-based.

Why is using MD5 for password hashing dangerous even with a salt?

MD5 is a fast hash — modern GPUs can compute billions of MD5 hashes per second. A salt prevents rainbow table attacks (pre-computed hash lookups), but it does not prevent brute force. With a salt, an attacker must brute force each password individually — but with MD5 and a GPU, billions of guesses per second means an 8-character password is cracked in seconds. Argon2id and bcrypt are intentionally slow (configurable work factor) — they are designed to make brute force computationally infeasible even with GPU acceleration.

From the books

OWASP Testing Guide (owasp.org)

The definitive reference for web application security testing — covers test cases for every OWASP Top 10 category with step-by-step methodology.

The Web Application Hacker's Handbook (Stuttard & Pinto)

Comprehensive guide to web application attack techniques. Understanding attacks from the attacker's perspective is the most effective way to write secure code.

🧠Mental Model

💡 Analogy

The OWASP Top 10 is the driver's test for web security

⚡ Core Idea

Just as every driver must know what a stop sign means, every engineer writing web code must know what SQL injection, broken access control, and XSS mean — and be able to recognise them in code they write and review. These are not advanced hacking techniques; they are basic hygiene that every engineer is expected to understand.

🎯 Why It Matters

The same 10 vulnerability classes appear in breaches year after year. Equifax (A06), Capital One (SSRF/A10), Optus (A01), Yahoo (A02) — these were preventable with knowledge that is freely available. The OWASP Top 10 is the minimum baseline for any engineer writing production code.

Ready to see how this works in the cloud?

Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.

View role-based paths

Sign in to track your progress and mark lessons complete.

Discussion

Questions? Discuss in the community or start a thread below.

Join Discord

In-app Q&A

Sign in to start or join a thread.