The OWASP Top 10 is the most widely referenced list in application security. Compliance frameworks cite it. Developers study it. Security teams build their programs around it. But after hundreds of web application penetration tests, we can tell you with confidence that the list and reality do not line up the way most people assume.
Some OWASP categories appear in virtually every engagement we run. Others are so rare that we might see them once or twice a year. The ranking itself is based on data contributions from organizations worldwide, covering incidence rates and exploit severity.[1] That methodology is sound, but it produces a list optimized for breadth of coverage, not frequency of exploitation. As penetration testers, we care about what actually breaks.
This article walks through all ten categories from the 2021 OWASP Top 10, maps each one to what we actually encounter in the field, and explains why some categories dominate while others barely register. If you are building a security program or prioritizing remediation, this is where to focus your resources.
A01:2021 - Broken Access Control (The Undisputed Champion)
This is the single most common vulnerability category we find. It is not close. Broken access control appeared in OWASP's data in 94% of applications tested, with over 318,000 occurrences.[1] Our experience matches that number almost exactly.
The most frequent manifestation is Insecure Direct Object References (IDOR). A user changes an ID parameter in a URL or API request and gains access to another user's data. We test this with Burp Suite's Repeater by simply swapping IDs in authenticated requests. In a recent SaaS engagement, changing /api/v1/invoices/4521 to /api/v1/invoices/4522 returned another customer's billing data, including names, addresses, and payment amounts. No authorization check existed on the server side.
What We Test For
- Horizontal privilege escalation: Accessing resources belonging to other users at the same privilege level. We use Burp Suite's Autorize extension to automate this across every endpoint in scope.[2]
- Vertical privilege escalation: Performing admin-level actions from a regular user account. We capture admin requests, replay them with low-privilege session tokens, and observe what the server allows.
- Missing function-level access control: Accessing admin panels, internal dashboards, or debug endpoints by simply navigating to the URL. We use tools like feroxbuster and ffuf for directory brute-forcing to find hidden endpoints.
- CORS misconfigurations: Overly permissive Cross-Origin Resource Sharing headers that allow malicious sites to read authenticated API responses. We check whether
Access-Control-Allow-Originreflects arbitrary origins.
Why it dominates: Broken access control is fundamentally an application logic problem. Scanners cannot reliably detect it because they do not understand your business rules. It requires manual testing with multiple user roles, and most development teams only test the "happy path" with one account.
A02:2021 - Cryptographic Failures
This category, formerly called "Sensitive Data Exposure," covers failures in cryptography that lead to data leakage. We encounter this regularly, but the findings tend to cluster around a few specific patterns rather than spanning the full range OWASP describes.
What We Actually Find
Weak TLS configurations are the most common. We run testssl.sh against every in-scope domain and routinely find TLS 1.0 or 1.1 still enabled, weak cipher suites like RC4 or 3DES, and missing HTTP Strict Transport Security (HSTS) headers. These are not theoretical risks. Downgrade attacks like POODLE (CVE-2014-3566) exploit exactly these weaknesses.[3]
Cleartext transmission of sensitive data still appears more often than you would expect. Internal APIs communicating over HTTP instead of HTTPS, mobile applications sending credentials without TLS pinning, and login forms served over HTTPS but submitting to HTTP endpoints.
Weak password hashing is harder to find during a black-box test, but when we get access to a database through SQL injection or during a white-box review, we regularly see MD5, SHA-1, or unsalted SHA-256 used for password storage instead of bcrypt, scrypt, or Argon2.
What we rarely find: truly broken custom cryptography implementations. Most teams use established libraries. The failures are in configuration and selection, not in rolling their own crypto.
A03:2021 - Injection
Injection dropped from the number one spot to number three in the 2021 update, and our testing data reflects that shift. SQL injection still exists, but it is far less common than it was five years ago. Frameworks like Django, Rails, and Laravel use parameterized queries by default. The low-hanging fruit has been largely picked.
Where Injection Still Thrives
SQL injection in legacy applications is alive and well. We recently found a classic error-based SQLi in a healthcare application's search feature that was built on raw PHP string concatenation. We confirmed it with sqlmap, which dumped the entire database in under 30 minutes.[4]
NoSQL injection is the modern variant. MongoDB applications that accept JSON input without validation are vulnerable to operator injection. Sending {"username": {"$ne": ""}, "password": {"$ne": ""}} to a login endpoint bypasses authentication entirely. We see this in Node.js applications that pass request bodies directly to Mongoose queries.
Server-Side Template Injection (SSTI) is increasingly common in applications using Jinja2, Twig, or Freemarker. When user input lands inside a template expression, it can lead to remote code execution. We test for this by injecting {{7*7}} and checking if the response contains 49. The tplmap tool automates exploitation across multiple template engines.[5]
Cross-Site Scripting (XSS) is now grouped under injection in the OWASP taxonomy, and it remains extremely common. Stored XSS in user profile fields, reflected XSS in search parameters, and DOM-based XSS in single-page applications. We find XSS in roughly 60-70% of web application assessments.
A04:2021 - Insecure Design
This was a new category in the 2021 update, and it is the most subjective one on the list. Insecure design refers to fundamental architectural flaws, not implementation bugs. It is about threat modeling failures where the application was designed without considering adversarial use cases.
Real Examples We Encounter
- Password reset flows that leak tokens: An application that includes the reset token in a GET parameter, causing it to appear in browser history, server logs, and Referer headers sent to third-party analytics scripts.
- Rate limiting gaps: Login forms with no rate limiting or account lockout, allowing unlimited brute-force attempts. We use Burp Suite's Intruder to demonstrate this by running a wordlist against the login endpoint at hundreds of requests per second.
- Business logic flaws: An e-commerce application that validates the item price on the client side but not the server side, allowing us to change the price to $0.01 by modifying the POST request. Another common example is coupon codes that can be stacked infinitely because the backend does not track how many times a discount has been applied.
These findings are among the highest-impact issues we report, but they require deep understanding of the application's business logic. Automated scanners will never find them.
A05:2021 - Security Misconfiguration
If broken access control is the most impactful finding category, security misconfiguration is the most pervasive. Nearly every engagement produces at least a handful of misconfig findings.
The Usual Suspects
Default credentials are still shockingly common. We check every admin panel, database interface, and management console for default username/password combinations. Tools like default-http-login-hunter and Nmap's http-default-accounts script automate this process. We recently accessed a production Grafana dashboard with admin/admin credentials.
Verbose error messages that expose stack traces, database names, file paths, and framework versions. Django debug mode left enabled in production is a classic. It hands us the complete settings file, database connection strings, and every URL route in the application.
Missing security headers appear in nearly 100% of our assessments. We check for Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and Permissions-Policy. Most applications are missing at least two or three of these.
Cloud misconfigurations deserve their own mention. Publicly accessible S3 buckets, overly permissive IAM roles, security groups allowing 0.0.0.0/0 access to management ports, and unencrypted EBS volumes. We use tools like ScoutSuite and Prowler for AWS configuration auditing.[6]
The configuration sprawl problem: Modern applications have configurations scattered across web servers, application servers, frameworks, databases, cloud providers, CDNs, and container orchestration platforms. Every layer is an opportunity for misconfiguration. This is why we advocate for infrastructure-as-code with security linting baked into the CI/CD pipeline.
A06:2021 - Vulnerable and Outdated Components
This category is straightforward: using libraries, frameworks, or platforms with known vulnerabilities. We find it in every single engagement without exception. The challenge is not whether an application has outdated components, but whether any of them are actually exploitable in context.
Our approach is to run Software Composition Analysis (SCA) as part of the assessment. For JavaScript applications, npm audit typically reveals dozens of vulnerable dependencies. For Java applications, OWASP Dependency-Check scans the classpath.[7] For container images, Trivy or Grype scan for vulnerable OS packages and application dependencies.
The real question is exploitability. A vulnerable version of lodash deep in a dependency tree might not be reachable from any user-controlled input. We triage every finding by checking whether the vulnerable code path is actually exposed. This is what separates a useful pentest from a scanner dump.
Notable Patterns
- jQuery versions below 3.5.0 with known XSS vulnerabilities (CVE-2020-11022) still appear in over half of the applications we test.
- Apache Struts has been responsible for some of the largest breaches in history, including Equifax (CVE-2017-5638). We still find unpatched Struts instances in enterprise environments.[8]
- WordPress plugins are a goldmine. Core WordPress is reasonably secure, but the plugin ecosystem is a minefield of SQL injection, XSS, and file upload vulnerabilities. WPScan identifies vulnerable plugins quickly.
A07:2021 - Identification and Authentication Failures
Authentication testing is a core part of every web application engagement. This category covers weak authentication mechanisms, and we find issues here in roughly 40-50% of our assessments.
Weak password policies remain the most common finding. Applications that accept "password123" without complaint, do not enforce minimum length, or fail to check passwords against known breach lists (like the Have I Been Pwned API). We also check for username enumeration, which is when the application responds differently to valid and invalid usernames, allowing attackers to confirm which accounts exist before brute-forcing passwords.
Session management flaws include session tokens that do not rotate after login (enabling session fixation), session tokens in URLs, overly long session timeouts, and missing secure/HttpOnly/SameSite attributes on session cookies. We inspect cookies in Burp Suite and test session lifecycle thoroughly.
JWT vulnerabilities are increasingly common as more applications adopt token-based authentication. We test for algorithm confusion attacks (changing RS256 to HS256), missing signature verification, the "none" algorithm bypass, and JWK injection. The jwt_tool from ticarpi automates most of these checks.
A08:2021 - Software and Data Integrity Failures
This is one of the rarer categories in our testing experience. It covers failures to verify the integrity of software updates, CI/CD pipelines, and deserialization of untrusted data.
The most common finding we see here is insecure deserialization. Java applications using ObjectInputStream, PHP applications with unserialize() on user input, and Python applications using pickle with untrusted data. When we find deserialization endpoints, tools like ysoserial (for Java) let us generate payloads that achieve remote code execution.[9]
Supply chain integrity issues, like missing Subresource Integrity (SRI) hashes on CDN-hosted JavaScript, are also common. If an attacker compromises the CDN or performs a man-in-the-middle attack, they can inject malicious code into every page that loads the script. We flag every externally hosted script that lacks an SRI hash.
CI/CD pipeline attacks are generally out of scope for standard web application pentests, but we occasionally assess them during broader security engagements. Misconfigured GitHub Actions workflows that expose secrets, Jenkins instances with unauthenticated access, and artifact repositories without integrity verification are the typical findings.
A09:2021 - Security Logging and Monitoring Failures
This is the hardest category to test during a standard penetration test, and honestly, we rarely report it as a standalone finding. We can observe its absence indirectly. If we run hundreds of failed login attempts, trigger multiple SQL injection payloads, and perform directory brute-forcing over several days without being detected or blocked, that tells us something about the target's monitoring posture.
When clients request a more comprehensive assessment, we check for:
- Whether login attempts (successful and failed) are logged with sufficient detail.
- Whether API requests include audit trails tied to authenticated users.
- Whether logs are stored in a centralized, tamper-resistant system.
- Whether alerting exists for anomalous patterns like credential stuffing or privilege escalation attempts.
The reality is that most organizations have some logging in place, but the logs are not monitored in real time, are not retained long enough, or do not capture the right data points. This is a detection gap, not a vulnerability in the traditional sense, and it rarely shows up in a pentest report as a critical finding.
A10:2021 - Server-Side Request Forgery (SSRF)
SSRF was new to the Top 10 in 2021, and its inclusion was somewhat controversial. The data showed a relatively low incidence rate, but the community voted it in because of its high impact potential, particularly in cloud environments where the instance metadata service at 169.254.169.254 can expose IAM credentials.[10]
We find SSRF less frequently than most other categories, but when we do find it, the impact is almost always critical. Common locations include:
- URL preview features: Applications that fetch a URL to generate a preview (like Slack's link unfurling) can be tricked into requesting internal resources.
- PDF generators: Server-side HTML-to-PDF conversion (using wkhtmltopdf, Puppeteer, or similar) often processes user-supplied HTML, including external resource references that can target internal hosts.
- Webhook configurations: Applications that let users specify a webhook URL will make HTTP requests to that URL, potentially reaching internal services.
- Image processing: Features that download and resize images from user-supplied URLs.
When we find SSRF, we test for access to cloud metadata endpoints, internal service discovery by scanning RFC 1918 address ranges, and protocol smuggling (using gopher:// or file:// schemes to interact with internal services in unexpected ways).
The Frequency Gap: What the Ranking Misses
If we had to rank the OWASP Top 10 by how often each category appears in our penetration tests, the order would look very different:
- A01 - Broken Access Control: Found in 80-90% of engagements.
- A05 - Security Misconfiguration: Found in 85-95% of engagements.
- A06 - Vulnerable Components: Found in 95-100% of engagements (though severity varies wildly).
- A03 - Injection (primarily XSS): Found in 60-70% of engagements.
- A02 - Cryptographic Failures: Found in 50-60% of engagements.
- A07 - Authentication Failures: Found in 40-50% of engagements.
- A04 - Insecure Design: Found in 30-40% of engagements.
- A08 - Integrity Failures: Found in 10-20% of engagements.
- A10 - SSRF: Found in 10-15% of engagements.
- A09 - Logging Failures: Rarely reported as a standalone finding.
The takeaway is not that the OWASP Top 10 is wrong. It is a well-researched, data-driven list that serves its purpose as a broad awareness document. But if you are using it as your sole guide for security testing priorities, you are going to over-invest in some areas and under-invest in others.
What This Means for Your Security Program
Prioritize Access Control Testing
Broken access control cannot be found by automated scanners. It requires manual testing with multiple user roles, a thorough understanding of the application's authorization model, and creative thinking about how those controls might fail. If your pentest provider is not testing with at least two different user roles plus an unauthenticated session, they are missing the most common vulnerability category.
Do Not Ignore the "Boring" Findings
Missing security headers, outdated libraries, and verbose error messages might not sound exciting, but they stack up. A reflected XSS combined with a missing Content-Security-Policy header is exploitable. An outdated jQuery version combined with a DOM-based XSS sink is exploitable. Security misconfigurations provide the supporting conditions that turn minor issues into major ones.
Context Matters More Than Category
A SQL injection in a read-only public search feature is less critical than a broken access control issue that exposes customer PII. Severity depends on what data is at risk, what systems can be reached, and what business impact an exploit would cause. Treat the OWASP Top 10 as a starting point for coverage, not as a severity ranking.
Test Regularly, Not Just Annually
Applications change constantly. New features introduce new access control requirements, new integrations create new SSRF vectors, and new dependencies bring new vulnerabilities. Annual pentesting catches a snapshot. Quarterly or continuous testing catches the drift.
Sources
- OWASP Top 10:2021 - owasp.org
- Autorize - Burp Suite Extension for Authorization Testing - github.com/PortSwigger/autorize
- CVE-2014-3566 - POODLE SSLv3 Vulnerability - nvd.nist.gov
- sqlmap - Automatic SQL Injection and Database Takeover Tool - sqlmap.org
- tplmap - Server-Side Template Injection Exploitation Tool - github.com/epinna/tplmap
- Prowler - AWS Security Best Practices Assessment - github.com/prowler-cloud/prowler
- OWASP Dependency-Check - Software Composition Analysis - owasp.org
- CVE-2017-5638 - Apache Struts Remote Code Execution (Equifax Breach) - nvd.nist.gov
- ysoserial - Java Deserialization Exploitation Framework - github.com/frohoff/ysoserial
- OWASP Top 10:2021 - A10 Server-Side Request Forgery - owasp.org
Find Out What Is Actually Vulnerable
We test for every OWASP category with manual, context-driven techniques that scanners miss. Get a penetration test that tells you what actually matters.
Book a Consultation Our Services