Skip to content

OWASP Top 10 Overview

OWASP publishes the canonical risk-ranked list of web vulnerability classes. The list is not a checklist of bugs — it is a prioritization model used by every SAST/DAST vendor, every compliance regime (PCI DSS 6.5, ISO 27034), and every bug-bounty scope. Knowing why A01 is Broken Access Control (and not Injection, which it was in 2017) tells you how the threat landscape has moved in five years.

The Top 10 is built from incident data contributed by dozens of organizations (AppSec teams, SaaS providers, bug-bounty platforms). OWASP 2021 swapped the order based on incidence rate, exploitability, and impact. The structural shift from “injection is #1” to “broken access control is #1” reflects the move from monolithic SQL-backends to API-driven, microservice architectures where authorization logic lives in code, not in a query parser.

OWASP 2021 OWASP 2017
───────────────── ─────────────────
A01 Broken Access Control A01 Injection
A02 Cryptographic Failures A02 Broken Authentication
A03 Injection A03 Sensitive Data Exposure
A04 Insecure Design (new) A04 XXE
A05 Security Misconfiguration A05 Broken Access Control
A06 Vulnerable Components A06 Security Misconfig
A07 Identification & Auth Failure A07 XSS
A08 Software & Data Integrity A08 Insecure Deserialization
A09 Security Logging Failure A09 Vulnerable Components
A10 SSRF (new) A10 Insufficient Logging

Each entry is a class, not a single bug. A03 Injection covers SQLi, NoSQLi, command injection, LDAP injection, and XPath injection — all of which are separate modules in this handbook (W2, W8, W21).

  1. Data collection — OWASP surveys AppSec vendors and bug-bounty platforms for: vulnerability category, incidence rate across tested applications, exploitability (via CVSS), and impact. The 2021 corpus was ~500,000 vulnerabilities across 40 firms.
  2. Categorization — submissions are mapped to a fixed taxonomy (CWE IDs). A01 Broken Access Control alone maps to 34 CWEs (CWE-200, CWE-201, CWE-352, CWE-862, CWE-863…).
  3. Ranking — four factors: incidence, exploitability (CVSS weighted), impact (technical + business), and detectability. The 2021 list introduced two new categories (Insecure Design, SSRF) precisely because they failed to map cleanly to any 2017 category.
  4. Mapping to controls — each category references the OWASP ASVS (Application Security Verification Standard), the OWASP Proactive Controls, and the Cheat Sheet series. A01 → ASVS V4 Access Control, Proactive Control C7.
  5. Tooling alignment — SAST vendors map rule IDs to OWASP categories. Semgrep, Checkmarx, Veracode all emit findings tagged OWASP A01:2021 so a CISO can roll up by OWASP class in a single chart.
OWASP A##ClassExample Bug ClassCWE
A01:2021Broken Access ControlIDOR, missing function-level authzCWE-862
A02:2021Cryptographic FailuresPlaintext storage, weak TLS, deprecated hashCWE-327
A03:2021InjectionSQLi, command injection, NoSQLiCWE-89, CWE-77
A04:2021Insecure DesignMissing rate-limit, no business-logic authzCWE-209
A05:2021Security MisconfigurationDefault creds, verbose errors, open S3CWE-16
A06:2021Vulnerable ComponentsLog4Shell (CVE-2021-44228), Equifax StrutsCWE-1104
A07:2021Identification & Auth FailureCredential stuffing, no MFA, weak sessionCWE-287
A08:2021Software & Data IntegrityUnsigned updates, insecure deserializationCWE-502
A09:2021Security Logging FailureNo audit log on auth eventsCWE-778
A10:2021SSRFInternal metadata, IMDSv1 abuseCWE-918
Terminal window
# Run OWASP ZAP baseline scan against a target — passive only, no payloads
zap-cli --zap-url http://localhost:8080 quick-scan -s all -o '-config scanner.level=HIGH' https://example.com
# Nuclei with OWASP Top 10 tag from the public template repo
nuclei -u https://example.com -t ~/nuclei-templates/http/cves/ -severity critical,high -tags owasp-top-10
# Burp Suite — passive scan rules are tagged with OWASP A01-A10
# Professional & Community have the "OWASP Top 10 2021" scan profile
# Scanner options → Issues → filter by A## category
# Semgrep with the OWASP Top 10 pack
semgrep ci --config p/owasp-top-10 --config p/owasp-top-ten src/
# Quickly inspect headers and TLS posture against ASVS V9 (communications)
curl -sI https://example.com | grep -iE 'strict-transport|x-frame|content-security|x-content-type'
testssl.sh --severity HIGH https://example.com

ModSecurity OWASP CRS 4.x is mapped to OWASP categories by the rule-set’s tag:owasp-top-10 metadata. Each rule carries both an OWASP A## tag and a CWE tag:

SecRule ARGS|REQUEST_HEADERS "@rx ..." \
"id:942100, phase:2, t:none, \
tag:'OWASP_TOP_10/A03', tag:'OWASP_CRS/WEAKNESS', \
tag:'CWE-89', ..."

Rule family mapping (CRS 4.0):

  • 932100 series — RCE / Command Injection → A03, CWE-77
  • 942100 series — SQLi → A03, CWE-89
  • 941100 series — XSS → (was A07:2017, now folded into A03 client-side)
  • 930100 series — LFI/RFI/Path Traversal → A01, CWE-22
  • 920300 series — Protocol / request smuggling → A05, CWE-16
  • 934100 series — SSRF / Node sandbox → A10, CWE-918

MITRE ATT&CK T1190 — Exploit Public-Facing Application. This single technique is the upstream ATT&CK mapping for nearly every OWASP Top 10 entry.

Sysmon Event ID 1 — ProcessCreate. When a web stack spawns a child process (cmd.exe, /bin/sh, powershell.exe) originating from a web-server parent (w3wp.exe, nginx worker, php-fpm), that is a downstream signal of A03/A05.

Wazuh rule 31100 family — web attacks (SQLi, XSS, RCE) sourced from ModSecurity audit logs forwarded by Filebeat [verify].

Category laundering. A single payload that hits three OWASP classes at once will be reported as one by a WAF. Example: a SSRF request to an internal metadata service that returns IAM credentials, used to then call an internal API without authorization — that is A10 → A01 → A03 in one chain. Most detection tooling reports only the first alert. Defense: enable chained-rule alerting in ModSecurity CRS pl1 paranoia level and ship the full transaction log to a SIEM that can correlate.

A05 misconfiguration as a mask. Many A03 injection failures only work because the framework was misconfigured to expose verbose errors (A05). Turning off display_errors in PHP or DEBUG=True in Django removes the oracle without fixing the injection. This is why A05 ranks so high — it is an enabler for A03/A07.

EvasionWhat it defeatsHow to detect
Encoding (%2f, double-URL)Naive keyword WAFsUse libinjection + decoded byte matching (CRS does this)
HPP (HTTP Parameter Pollution)Single-value rule matchtx.args aggregate across all params
Case variation (SeLeCt)Case-sensitive regexAlways use (?i) or pre-lowercase with t:lowercase
Comment insertion (S/**/ELECT)Token regexStrip inline comments pre-match (t:removeComments)
Unicode normalizationASCII-only matchersApply t:urlDecodeUni first

⚠️ What caught me: An internal scan reported “OWASP A06 zero findings” for an app because the SAST tool only scanned the requirements.txt and the project had migrated to a private Poetry index. The Log4j-equivalent dependency (a private fork of python-jose) had a known CVE in its changelog but no public advisory the scanner could ingest. OWASP A06 is hard because the corpus is external to your code. Lesson: vulnerability databases are incomplete by design; SBOM + manual changelog review is the floor, not the ceiling.

Container: OWASP Juice Shop (bkimminich/juice-shop) — covers all 10 categories with 100+ challenges tagged by OWASP class.

Terminal window
docker run --rm -p 3000:3000 bkimminich/juice-shop
# Score board at http://localhost:3000/#/score-board

Objective: solve one challenge in each of the A01–A10 categories and capture the scoreboard completion percentage per category.

Expected flag format: flag{owasp_top10_2021_a04_insecure_design_solved}.

Detection that should fire: any WAF or RASP in front of Juice Shop — ModSecurity CRS, Coraza, OpenRASP — will alert on challenges in A03 (SQLi login bypass), A07 (JWT none-algorithm), and A10 (SSRF via ftp:// URL in the B2B profile).

Conceptual: why did OWASP demote Injection from #1 in 2017 to #3 in 2021, and what does that say about how the underlying application architecture has changed?

Scenario: a SAST report shows 0 findings for OWASP A06 (Vulnerable Components) but the SBOM lists 12 dependencies with known CVEs. What is the most likely gap, and how would you close it?

Technical: walk through how ModSecurity CRS maps a single SQLi rule to both A03:2021 and CWE-89, and why that dual tagging matters for compliance reporting.

Compare A08:2021 (Software & Data Integrity) with CWE-502 (Insecure Deserialization). Are they equivalent? If not, what is in A08 that is not in CWE-502?

Conceptual: A04 (Insecure Design) was a brand-new category in 2021 and is sometimes criticized as “untestable.” Give one concrete example of an Insecure Design finding that is NOT already covered by A01 or A07.

→ W2 (SQL Injection) · W8 (Command Injection) · F11 (Threat Modeling)