OWASP Top 10 Explained: The 10 Most Critical Web Application Security Risks
OWASP Top 10 explained with real examples: broken access control, injection, cryptographic failures and all 10 risks, how to test each one safely, and how to fix it.
OWASP Top 10 Explained: The 10 Most Critical Web Application Security Risks
Most web application breaches are not caused by exotic zero-day exploits. They are caused by the same ten families of mistakes, repeated across thousands of applications. The OWASP Top 10 names those families, in order of risk, so developers know what to fix first and testers know what to look for first. Learn this list properly and you will recognise most web vulnerabilities on sight.
> Only test applications you own or have explicit written permission to test. Practise the testing steps in this guide in a lab such as OWASP Juice Shop, DVWA, or WebGoat — never against a live site you do not own.
What Is OWASP?
OWASP, the Open Worldwide Application Security Project, is a non-profit community that publishes free, openly available security guidance. Its Top 10 is not a law and not a complete list of every possible vulnerability. It is a consensus ranking, built from vulnerability data contributed by security teams and tool vendors, of the risks with the highest combination of prevalence and impact.
That is why the list changes slowly. The 2021 edition — the edition this guide explains — moved Broken Access Control to number one, renamed Sensitive Data Exposure to Cryptographic Failures to focus on the root cause, and added three new categories: Insecure Design, Software and Data Integrity Failures, and Server-Side Request Forgery (SSRF). OWASP has discussed a newer edition since then, so check owasp.org before quoting an edition number in a report. The 2021 categories below remain the standard reference most teams and interviews use.
How to Use This Guide
Each risk below follows the same pattern: what it is, a concrete example, how to test for it safely in a lab, and how to fix it. Read the summary table first, then work through the categories in order. At the end you will find a testing workflow, a developer checklist, and a knowledge check.
The OWASP Top 10 (2021) at a Glance
| Rank | Risk | In one line |
| A01 | Broken Access Control | Users can do things they should not be allowed to do. |
| A02 | Cryptographic Failures | Sensitive data is not protected properly in transit or at rest. |
| A03 | Injection | Untrusted input is treated as a command. |
| A04 | Insecure Design | The design itself has no controls, so no implementation fix is enough. |
| A05 | Security Misconfiguration | Defaults, errors, and headers leak information or leave doors open. |
| A06 | Vulnerable and Outdated Components | Known-vulnerable libraries and frameworks are still running. |
| A07 | Identification and Authentication Failures | Login, session, and password recovery can be abused. |
| A08 | Software and Data Integrity Failures | Updates, libraries, and pipelines are trusted without verification. |
| A09 | Security Logging and Monitoring Failures | Attacks happen, but nobody notices in time. |
| A10 | Server-Side Request Forgery (SSRF) | The server is tricked into making requests the attacker chooses. |
A01: Broken Access Control
What it is: Access control decides who can do what. It is broken when the application fails to enforce those rules on the server — for every request, for every function, and for every object.
Example: You are logged in and your profile URL contains user_id=1001. You change it to user_id=1002 and see someone else's private account details, with no error and no block. That is an Insecure Direct Object Reference (IDOR), the classic broken access control bug. The same failure lets ordinary users reach admin functions, change other users' data, or escalate their own privileges, simply by requesting a URL or API endpoint the application never checked.
How to test (lab only): In Juice Shop or DVWA, log in as a low-privilege user, then try the same request with another user's ID, try admin URLs directly, and try API actions (POST, PUT, DELETE) without the expected role. Record every request the server accepts that it should have rejected.
How to fix: Deny by default — reject access unless a rule explicitly allows it. Enforce access control on the server for every object and function, never in the browser alone. Use one central authorisation check, not a check copied into each page. Log access-control failures and alert on repeated attempts.
A02: Cryptographic Failures
What it is: Sensitive data is transmitted or stored without adequate protection: cleartext transmission, weak or outdated algorithms, missing encryption, or poor key management. OWASP renamed this category from Sensitive Data Exposure in 2021 precisely because the failure is in the cryptography, not just in the exposure.
Example: A database breach reveals passwords stored as fast, unsalted MD5 hashes, which modern hardware can crack in bulk. Or a login page loads over plain HTTP, so credentials cross the network in cleartext. Or an application encrypts data with a hard-coded key that ships in the source code.
How to test (lab only): Check whether sensitive pages enforce HTTPS, inspect what is stored for passwords and tokens, and look for hard-coded secrets and weak algorithms in the lab application's code and configuration.
How to fix: Enforce TLS everywhere, not just on login pages. Store passwords with a slow, salted, modern password-hashing algorithm such as bcrypt or Argon2 — never MD5 or SHA-1. Encrypt sensitive data at rest, manage keys separately from the data, rotate keys, and never hard-code secrets. Disable outdated protocols and weak ciphers.
A03: Injection
What it is: Untrusted data is sent to an interpreter — a database, a shell, an LDAP directory, or an XML parser — and treated as a command instead of as data. SQL injection is the best-known variant, but the category covers all of them.
Example: A login form builds a query by concatenating user input, and an attacker enters ' OR '1'='1 in the username field. The query's logic changes, and the attacker logs in without a valid password. The same pattern works against operating-system commands, LDAP queries, and XML parsers when input is not separated from code.
How to test (lab only): In DVWA's SQL injection module, try a single quote to break the query, then a controlled boolean condition, then read the result. Confirm the flaw by the application's behaviour, not by guessing — and keep every test inside the lab.
How to fix: Use parameterised queries (prepared statements) so input can never change the query's structure. Validate input by allow-list where a format is known, and escape output for its context. Never build queries, commands, or LDAP filters by concatenating user input. Use an ORM or a safe API, and limit database accounts to the least privilege they need.
A04: Insecure Design
What it is: A04 is different from the other categories: it is not a coding bug but a missing control in the design itself. If the design never included rate limiting, threat modelling, or a secure password-recovery flow, no amount of careful coding in that design will add it.
Example: A password-reset flow that accepts any answer to a security question, or an application with no limit on login attempts, so credential stuffing runs unchecked. The code works exactly as designed — the design is the vulnerability.
How to test (lab only): Review the lab application's flows before you test code: what happens on repeated failed logins, on password reset, on account lockout, on high-value actions? Missing controls are findings even when no single line of code is "wrong".
How to fix: Threat-model new features before building them: what can go wrong, and what control prevents it? Write secure design patterns into the project — rate limiting, account lockout, and safe recovery flows — and review designs, not just code, before release. OWASP's Application Security Verification Standard (ASVS) is a useful design checklist.
A05: Security Misconfiguration
What it is: The application, framework, or server is left in an insecure default state: unnecessary features enabled, verbose error messages, missing security headers, default credentials, or cloud storage left public.
Example: A server returns stack traces in error pages, revealing framework versions and file paths. Or directory listing is enabled, default admin credentials still work, or a cloud bucket is publicly readable. Attackers automate the search for exactly these defaults.
How to test (lab only): Crawl the lab application for error pages, check response headers, try default credentials, and list what the server exposes that a user should never see. Tools such as [Nikto](/tools/nikto) automate much of this misconfiguration checking.
How to fix: Harden by a repeatable checklist: remove defaults and sample applications, disable directory listing and unused features, return generic error messages, set security headers (including Content-Security-Policy and HSTS), and review cloud and server configuration on every deployment, not just the first one.
A06: Vulnerable and Outdated Components
What it is: The application runs libraries, frameworks, or other components with known vulnerabilities — often because nobody knows the component is there, or because updating it was postponed.
Example: A site runs an old version of a JavaScript library or a content management system with a published critical vulnerability. Attackers do not need to find a new bug; they scan for the known version and use the public exploit.
How to test (lab only): Inventory the lab application's components and versions, then check them against a vulnerability database. Dependency-scanning tools automate this inventory; manual version banners in responses and headers are a starting point, not a complete inventory.
How to fix: Keep a software bill of materials — a list of every component and version you ship. Subscribe to security advisories for those components, patch on a schedule, remove unused dependencies, and prefer components that are actively maintained. Test updates before deploying them, but do not let testing become an excuse to stay vulnerable for months.
A07: Identification and Authentication Failures
What it is: Login, session management, and credential recovery can be abused: weak or breached passwords allowed, no protection against brute force, sessions that never expire, or predictable session tokens.
Example: An application allows unlimited login attempts with no lockout or delay, so password spraying succeeds. Or a session cookie has no expiry, so a stolen cookie works indefinitely. Or password reset links never expire and are sent over an insecure channel.
How to test (lab only): In a lab, test login rate limiting, session expiry after logout and after inactivity, password policy, and reset-token behaviour. Never test these against a real account that is not yours.
How to fix: Require strong passwords and check new passwords against breached-password lists. Enforce multi-factor authentication, especially for admin and remote access. Limit and delay failed logins, use unpredictable session tokens, expire sessions on logout and after inactivity, and make reset tokens short-lived, single-use, and sent over a secure channel.
A08: Software and Data Integrity Failures
What it is: Code, updates, and data are trusted without verification: unsigned updates, libraries fetched over insecure channels, deserialised data from untrusted sources, or CI/CD pipelines with no integrity checks.
Example: An application auto-updates a plugin from an unverified source, or accepts serialised objects from a client and deserialises them without checking what they contain. A compromised library or pipeline then compromises every application that trusts it.
How to test (lab only): Trace how the lab application receives updates and third-party code: is anything signed, hashed, or pinned? Is deserialised data validated before use? Gaps in that chain are the finding.
How to fix: Verify signatures and hashes for updates and libraries, pin dependency versions, use a private, access-controlled pipeline, and never deserialise untrusted data. Treat the build pipeline as part of the application: restrict who can change it, and log every change.
A09: Security Logging and Monitoring Failures
What it is: The application does not log security-relevant events, logs them in a way nobody reads, or keeps logs that attackers can alter or delete. Breaches are then discovered months later, if at all — and incident response has no timeline to work from.
Example: Repeated failed logins, access-control failures, and input-validation errors are never logged, so a brute-force campaign runs for weeks unnoticed. Or logs exist but are stored on the same server the attacker compromised, so they are deleted with the evidence.
How to test (lab only): Trigger failures in the lab — failed logins, forbidden access, malformed input — and check what is recorded, where it is stored, and whether anyone would be alerted. A log nobody reviews is barely better than no log.
How to fix: Log logins, access-control failures, input-validation failures, and server-side errors with enough context (time, user, action, outcome) to reconstruct an incident. Protect logs from tampering, forward them to a central store, and alert on patterns — repeated failures, privilege changes, and unusual access — not just on single events.
A10: Server-Side Request Forgery (SSRF)
What it is: The application fetches a URL supplied by the user, and an attacker supplies a URL pointing somewhere the server should never contact: internal services, cloud metadata endpoints, or admin interfaces that are only reachable from the server itself.
Example: An image-fetch feature accepts a URL. An attacker gives it the cloud metadata address, and the server — which can reach that address — returns the cloud credentials in its response. The attacker never contacted the internal service directly; the server did it for them.
How to test (lab only): In a lab with a URL-fetch feature, try internal addresses and observe whether the server's response reflects internal content. Keep this strictly in the lab: SSRF against real infrastructure can expose real credentials.
How to fix: Validate and allow-list URLs on the server, block private and link-local address ranges, disable URL redirects to internal hosts, and run outbound-fetching services with no access to internal networks or metadata endpoints. For the full picture, read [SSRF Explained](/learn/ssrf-explained).
How to Test the OWASP Top 10 in Kali Linux
Work through the list in a lab, in order, with a proxy in front of you:
For broader web fundamentals, pair this guide with [Web Security Fundamentals](/learn/web-security-fundamentals), and for injection in depth, read [SQL Injection Basics](/learn/sql-injection-basics).
Developer Checklist
Common Mistakes
Summary
The OWASP Top 10 is a prioritisation tool, not a trivia list. Broken access control, cryptographic failures, and injection sit at the top because they are common, impactful, and — with server-side checks, parameterised queries, and proper cryptography — largely preventable. The rest of the list is about the systems around the code: design, configuration, components, authentication, integrity, logging, and what the server itself can be made to request. Learn the ten categories, practise them in a lab, and use the checklist on every feature you build or test.
Knowledge Check
Keep Learning
Frequently Asked Questions
Continue Learning
Web Security Fundamentals: OWASP Top 10 and Beyond
A comprehensive guide to web application security covering the OWASP Top 10 vulnerabilities, defense in depth strategies, and secure development lifecycle practices.
Web Security · IntermediateIDOR Explained: Insecure Direct Object References
Learn about Insecure Direct Object Reference vulnerabilities where attackers access unauthorized data by manipulating object identifiers in requests.
Web Security · IntermediateSQL Injection Basics: Understanding and Preventing Database Attacks
Learn how SQL injection attacks work, how to test for them, and how to prevent them in your web applications using parameterized queries and other defenses.
Web Security · IntermediateCommand Injection: Exploiting System Commands in Web Apps
Understand command injection attacks where attackers execute arbitrary system commands through vulnerable applications and how to prevent them.
Related Security Tools
Security Headers Checker
Check HTTP security headers (CSP, HSTS, X-Frame-Options, X-XSS-Protection, Referrer-Policy, and more) with security scoring.
Web SecuritySSL Certificate Checker
Check SSL/TLS certificate details including issuer, expiration date, days remaining, validity, and security grade.
Web SecurityWebsite Security Score
Generate a comprehensive 0-100 security score based on SSL status, security headers, domain age, and DNS configuration.
Web ApplicationCommix
Commix (Command Injection Exploiter) is an automated tool designed to test, detect, and exploit command injection vulnerabilities in web applications, facilitating automated OS shell access.