Skip to content
Pentesting and ethical hacking

OWASP Top 10 explained with examples

The OWASP Top 10 2025 explained category by category, with a lab-only example for each, what changed from 2021, and how the API Top 10 differs.

LearnCyber editorial team, reviewed by Hackrowd Technology’s penetration testers · · 9 min read

The OWASP Top 10 is a community-built list of the ten most important categories of web application security risk, and the current edition is the OWASP Top 10:2025, which OWASP has published as a final release. It replaces the 2021 list, which you’ll still see quoted in job adverts, course outlines and older reports.

Below, each of the ten categories gets a plain explanation, a short example you can reproduce in your own lab only, and a note on how defenders fix it. If you’re aiming for a web testing or AppSec role, this is the vocabulary every interviewer will expect you to know.

Legal note: only test systems you own or have written permission to test. Every example below targets a deliberately vulnerable app running on a private lab network.

What is the OWASP Top 10?

OWASP (the Open Worldwide Application Security Project) is a non-profit foundation that produces free security resources. The Top 10 is its best-known document: an awareness list, ranked using vulnerability data contributed by organisations plus a community survey that lets practitioners promote risks the data may not yet show.

Three things the Top 10 is not:

  • It isn’t a complete testing checklist. For that, use the OWASP Web Security Testing Guide (WSTG).
  • It isn’t a compliance standard. The OWASP Application Security Verification Standard (ASVS) is closer to that.
  • It isn’t a ranking of individual bugs. Each entry is a category that groups many weaknesses (CWEs) together.

The lab used in the examples

Every example assumes a small, isolated lab:

Host Role
10.10.20.2 Kali Linux attack VM
10.10.20.5:3000 OWASP Juice Shop (deliberately vulnerable shop)
10.10.20.11 A small intentionally vulnerable “acme-fintech.test” practice API you build yourself

OWASP Juice Shop is free and runs in Docker with one command, which makes it the easiest place to start:

docker run -d --name juice-shop -p 3000:3000 bkimminich/juice-shop

Keep the lab on a host-only or internal network. Most of these requests are easiest to see in an intercepting proxy; our Burp Suite tutorial for beginners walks through the setup.

The OWASP Top 10:2025 list

2025 rank Category Where it was in 2021
A01 Broken Access Control A01 (now also includes SSRF)
A02 Security Misconfiguration A05
A03 Software Supply Chain Failures Expanded from A06 Vulnerable and Outdated Components
A04 Cryptographic Failures A02
A05 Injection A03
A06 Insecure Design A04
A07 Authentication Failures A07 (Identification and Authentication Failures)
A08 Software or Data Integrity Failures A08
A09 Security Logging and Alerting Failures A09 (Logging and Monitoring)
A10 Mishandling of Exceptional Conditions New

Source: OWASP Top 10:2025 introduction. The headline changes: Server-Side Request Forgery, which had its own A10 slot in 2021, has been folded into Broken Access Control; supply chain risk gets a broader category; and a new category covers how applications behave when things go wrong.

A01:2025 Broken Access Control

What it is: a user can do or see something they shouldn’t. Classic cases are insecure direct object references (IDOR), missing checks on admin functions, and, from 2025, SSRF, where the server can be tricked into making requests on the attacker’s behalf.

Lab example (IDOR in Juice Shop): log in as a normal user, capture your basket request, then change the basket ID.

curl -s http://10.10.20.5:3000/rest/basket/2 \
  -H “Authorization: Bearer $USER_TOKEN”
{“status”:“success”,“data”:{“id”:2,“UserId”:2,“Products”:[{“name”:“Banana Juice (1000ml)”, ...}]}}

If your own basket is ID 6 and the app returns basket 2, owned by a different user, you’ve found broken object-level authorisation.

The fix: enforce authorisation on the server for every object, using the identity in the session rather than an ID the client sends. Deny by default.

A02:2025 Security Misconfiguration

What it is: insecure defaults, unnecessary features left on, verbose errors, missing hardening, exposed admin panels and directory listings.

Lab example: Juice Shop exposes a browsable directory.

curl -s http://10.10.20.5:3000/ftp/ | grep -o 'href=“[^”]*"' | head
href=“/ftp/acquisitions.md”
href=“/ftp/legal.md”
href=“/ftp/package.json.bak”
...

A backup file in a public directory is a typical misconfiguration finding. Check the response headers too with curl -sI; missing Content-Security-Policy or Strict-Transport-Security headers are common low-severity findings.

The fix: a repeatable hardening baseline, automated configuration checks in the deployment pipeline, and removing anything you don’t need.

A03:2025 Software Supply Chain Failures

What it is: risk that enters through the things you build with: third-party libraries, build tools, CI/CD pipelines, package registries and container images. In 2021 this was narrower (“vulnerable and outdated components”).

Lab example: clone a deliberately outdated practice project into your lab and audit its dependencies.

cd ~/lab/acme-fintech-api
npm audit --omit=dev
# npm audit report
...
3 vulnerabilities (1 moderate, 2 high)

To address all issues, run:
  npm audit fix

The interesting part for a tester is reading each advisory and asking whether the vulnerable function is actually reachable from the application.

The fix: maintain an inventory of components (a software bill of materials), pin versions with a lockfile, patch on a schedule, and protect the build pipeline itself with least-privilege access and reviewed changes.

A04:2025 Cryptographic Failures

What it is: sensitive data that isn’t protected properly: weak or no encryption in transit, outdated algorithms, poor key management, and passwords stored with fast, unsalted hashes.

Lab example: Juice Shop stores password hashes as unsalted MD5. Once you’ve extracted a hash in the lab (through the injection flaw below), crack it offline:

hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt
hashcat -m 0 hashes.txt --show
0192023a7bbd73250516f069df18b500:admin123

A fast hash of a weak password falls in seconds.

The fix: use a slow, salted password hashing algorithm such as Argon2id or bcrypt, enforce TLS everywhere, and keep keys out of source code.

A05:2025 Injection

What it is: untrusted input is interpreted as code or a query. SQL injection is the famous one; cross-site scripting (XSS) and OS command injection are in this category too.

Lab example (SQL injection login bypass in Juice Shop):

curl -s http://10.10.20.5:3000/rest/user/login \
  -H ‘Content-Type: application/json’ \
  -d “{\”email\“:\”' OR 1=1--\“,\”password\“:\”anything\“}”
{“authentication”:{“token”:“eyJ0eXAiOiJKV1Qi...”,“bid”:1,“umail”:“admin@juice-sh.op”}}

The quote closes the string in the SQL query, OR 1=1 makes the condition true, and -- comments out the password check. The app logs you in as the first user in the table, which is the administrator.

The fix: parameterised queries (prepared statements), context-aware output encoding for XSS, and input validation as an extra layer rather than the main defence. PortSwigger’s free Web Security Academy SQL injection labs are an excellent next step.

A06:2025 Insecure Design

What it is: a flaw in the design, not the code. Perfectly written code can still implement a dangerous idea. Business logic flaws live here.

Lab example: in Juice Shop, intercept the request that adds an item to your basket and set the quantity to a negative number. If the checkout total goes below zero, the design never considered that a quantity could be negative. A second design example for your own practice API: a one-time password check that allows unlimited attempts, because nobody wrote “lock after N failures” into the requirements.

The fix: threat modelling during design, abuse cases written alongside user stories, and server-side business rules that reject impossible values.

A07:2025 Authentication Failures

What it is: weaknesses in proving who someone is: no protection against credential stuffing or brute force, weak password policies, broken session handling, missing multi-factor authentication.

Lab example: test whether your practice API rate-limits logins, using a short wordlist.

hydra -l learner@acme-fintech.test -P top-100.txt 10.10.20.11 \
  http-post-form "/login:email=^USER^&password=^PASS^:F=Invalid credentials"
[80][http-post-form] host: 10.10.20.11   login: learner@acme-fintech.test   password: Summer2025!
1 of 1 target successfully completed, 1 valid password found

A hundred attempts without a lockout, delay or alert is itself the finding, even before a password is guessed.

The fix: multi-factor authentication, rate limiting and progressive delays, checks against known-breached passwords, and secure session tokens that are rotated on login.

A08:2025 Software or Data Integrity Failures

What it is: the application trusts data or code without checking it hasn’t been tampered with: unsigned updates, insecure deserialisation, or client-side data the server accepts as truth.

Lab example: your practice API stores the user’s role in a base64 cookie with no signature.

echo ‘eyJ1c2VyIjoibGVhcm5lciIsInJvbGUiOiJ1c2VyIn0=’ | base64 -d
# {“user”:“learner”,“role”:“user”}
echo -n ‘{“user”:“learner”,“role”:“admin”}’ | base64
# eyJ1c2VyIjoibGVhcm5lciIsInJvbGUiOiJhZG1pbiJ9

Send the edited cookie back. If the admin panel opens, the server trusted data it never verified. Base64 is encoding, not protection.

The fix: sign or encrypt anything the client holds (and verify the signature on the server), keep authorisation data server-side, verify signatures on updates and packages, and avoid deserialising untrusted input.

A09:2025 Security Logging and Alerting Failures

What it is: attacks happen and nobody notices. The 2025 name emphasises alerting: logs nobody looks at don’t help.

Lab example: this one is a defender’s exercise. Run the Hydra attack above, then look at what the application recorded.

grep -c ‘POST /login’ /var/log/nginx/access.log
# 100
grep -ci ‘failed login’ /var/log/acme-api/app.log
# 0

The web server saw every attempt; the application logged none of them as failed logins, and no alert fired. Now write a simple detection rule (for example, more than 20 failed logins for one account in five minutes) and rerun the attack to confirm it triggers.

The fix: log authentication events, access-control failures and input-validation failures with enough context to investigate; send them to a central system; and test that alerts actually fire.

A10:2025 Mishandling of Exceptional Conditions

What it is: the newest category. It covers what happens when an application meets something unexpected: malformed input, a dependency timing out, a transaction interrupted halfway. Applications that “fail open”, leak internal details in errors, or leave half-completed transactions behind belong here.

Lab example: send your practice API deliberately broken JSON.

curl -s -X POST http://10.10.20.11/api/transfer \
  -H ‘Content-Type: application/json’ -d ‘{“amount”:’
SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at /srv/acme-api/node_modules/body-parser/lib/types/json.js:...

A stack trace reveals the framework, file paths and libraries in use, which helps an attacker plan the next step. The more serious version, worth building into your lab, is a transfer endpoint that debits one account, then crashes before crediting the other, with no rollback.

The fix: handle errors centrally, return generic messages to users while logging detail internally, fail closed, and wrap multi-step operations in transactions that roll back on failure.

Is there a separate OWASP Top 10 for APIs?

Yes. The OWASP API Security Top 10 is a separate list, and its current edition is from 2023. It overlaps with the web list but is framed around how APIs fail: Broken Object Level Authorization (API1:2023) is the API version of IDOR, and it adds API-specific risks such as Unrestricted Resource Consumption and Improper Inventory Management (forgotten old API versions). If you test mobile apps or fintech backends, learn both lists.

How should a beginner study the OWASP Top 10?

  1. Read each category page on owasp.org, not a summary. The “How to prevent” sections are what interviewers ask about.
  2. Reproduce one example per category in Juice Shop or PortSwigger’s labs, and write a short finding for each: description, steps, impact, fix.
  3. Map it to certifications. Web application attacks feature in CompTIA PenTest+ (PT0-003); see our PenTest+ study guide.
  4. Learn both sides. Being able to explain the fix makes you useful to developers, which is most of the job.

Our guide on how to become a penetration tester from scratch shows where web testing fits in the wider skill set.

Questions

Is the OWASP Top 10 2025 final?

Yes. OWASP has published the 2025 edition as its eighth release, and the project page lists it as the current version.

Should I still learn the 2021 list?

Learn 2025, but know the 2021 names. Many job adverts, audit reports and course materials still reference them, and the mapping table above covers the differences.

Where did SSRF go?

It's now part of A01:2025 Broken Access Control.

Is the OWASP Top 10 enough for a web penetration test?

No. It's an awareness list. A proper test follows a methodology such as the OWASP Web Security Testing Guide.