OWASP Top 10 Testing Guide: How to Test for the Most Critical Web Vulnerabilities

OWASP Top 10 Testing Guide: How to Test for the Most Critical Web Vulnerabilities

Security testing is not optional. The OWASP Top 10 is the industry-standard reference for the most critical web application security risks, updated regularly based on real-world breach data. If your application has not been tested against every category in this list, it has not been security tested. This guide walks you through each category with specific test cases, tools, and HTTP-level examples you can use today.

What Is the OWASP Top 10?

The Open Web Application Security Project (OWASP) is a nonprofit that publishes freely available security guidance. Their Top 10 list, last updated in 2021, represents a broad consensus about the most impactful vulnerabilities affecting web applications. The list is not exhaustive — it is a starting point. Every application needs to be tested against all 10 categories, plus any domain-specific risks unique to its architecture.

The current 2021 list is:

  1. Broken Access Control
  2. Cryptographic Failures
  3. Injection
  4. Insecure Design
  5. Security Misconfiguration
  6. Vulnerable and Outdated Components
  7. Identification and Authentication Failures
  8. Software and Data Integrity Failures
  9. Security Logging and Monitoring Failures
  10. Server-Side Request Forgery (SSRF)

Let's test each one.


A01: Broken Access Control

Broken access control is the most common critical vulnerability today. It happens when users can act outside their intended permissions — accessing other users' data, performing admin functions, or bypassing authorization entirely.

Test Cases

Horizontal privilege escalation — Can user A access user B's resources?

GET /api/users/12345/profile HTTP/1.1
Host: app.example.com
Authorization: Bearer <user_A_token>

Change 12345 to another user's ID. If you get back user B's data, the application has broken access control.

Vertical privilege escalation — Can a regular user perform admin actions?

POST /api/admin/users/delete HTTP/1.1
Host: app.example.com
Authorization: Bearer <regular_user_token>
Content-Type: application/json

{"userId": "99"}

If this succeeds, authorization is not being checked on the server side.

Force browsing — Can unauthenticated users access protected pages?

GET /admin/dashboard HTTP/1.1
Host: app.example.com
(no Authorization header)

Tools

  • Burp Suite: Use the Repeater to replay requests with different tokens or no token
  • OWASP ZAP: Active scanner checks for access control issues automatically
  • Custom scripts: Automate IDOR testing across all resource IDs

A02: Cryptographic Failures

Previously called "Sensitive Data Exposure," this category covers failures in how applications protect data in transit and at rest. Common issues include weak cipher suites, unencrypted sensitive data, and broken TLS configurations.

Test Cases

TLS configuration testing with testssl.sh:

testssl.sh --severity HIGH https://app.example.com

Look for: SSLv3, TLS 1.0, RC4 ciphers, NULL ciphers, and expired certificates.

Mixed content — Does the page load HTTP resources over HTTPS?

Open browser DevTools → Console. Look for "Mixed Content" warnings.

Sensitive data in URLs — Tokens, passwords, or PII should never appear in query strings:

GET /reset?token=abc123&email=user@example.com HTTP/1.1

This exposes the token in server logs, browser history, and Referer headers.

Weak password hashing — If you have database access during a pentest, check that passwords are hashed with bcrypt, Argon2, or scrypt — not MD5 or SHA1.

Tools

  • testssl.sh: Comprehensive TLS scanner
  • SSL Labs: Online TLS grader at ssllabs.com/ssltest
  • OWASP ZAP: Flags insecure cookies and missing security headers

A03: Injection

Injection covers SQL injection, NoSQL injection, command injection, LDAP injection, and more. Any interpreter that receives untrusted data is a potential injection target.

Test Cases

SQL Injection — Try a simple payload in any input:

' OR '1'='1

Command Injection — Test file upload filenames, ping utilities, or any field passed to system commands:

; ls -la
| cat /etc/passwd
`whoami`

LDAP Injection — Test login forms against LDAP backends:

*)(|(password=*)

For full SQL injection testing detail, see our dedicated SQL injection testing guide.

Tools

  • sqlmap: Automated SQL injection detection and exploitation
  • Burp Suite: Manual injection testing with Intruder for fuzzing
  • OWASP ZAP: Active scanner with injection rules

A04: Insecure Design

Insecure design is about missing or inadequate security controls at the architecture level. Unlike the other categories, this is not a coding bug — it is a design flaw. Examples include missing rate limiting, no account lockout policy, or a password reset flow that can be manipulated.

Test Cases

Missing rate limiting on sensitive endpoints:

for i <span class="hljs-keyword">in $(<span class="hljs-built_in">seq 1 100); <span class="hljs-keyword">do
  curl -s -o /dev/null -w <span class="hljs-string">"%{http_code}\n" \
    -X POST https://app.example.com/api/login \
    -H <span class="hljs-string">"Content-Type: application/json" \
    -d <span class="hljs-string">'{"email":"user@test.com","password":"wrong"}'
<span class="hljs-keyword">done

If all 100 attempts return 200 or 401 without any throttling, rate limiting is missing.

Insecure password reset flow:

POST /api/reset-password HTTP/1.1
Host: app.example.com
Content-Type: application/json

{"email": "victim@example.com"}

Then immediately try the reset token from your own email for the victim's account — this tests for token reuse and predictable tokens.


A05: Security Misconfiguration

Misconfiguration is the most widespread vulnerability category. It includes default credentials, overly permissive CORS, exposed stack traces, verbose error messages, and unnecessary HTTP methods enabled.

Test Cases

Verbose error messages — Send malformed input and look for stack traces:

GET /api/users/abc HTTP/1.1
Host: app.example.com

If the response includes a Java stack trace, Python traceback, or SQL query, the application is leaking implementation details.

CORS misconfiguration:

GET /api/profile HTTP/1.1
Host: app.example.com
Origin: https://evil.com
Authorization: Bearer <token>

If the response includes Access-Control-Allow-Origin: https://evil.com, check whether cookies or credentials are also allowed. A wildcard origin with Access-Control-Allow-Credentials: true is a critical misconfiguration.

Unnecessary HTTP methods:

curl -X OPTIONS https://app.example.com/api/users -v

The response should not include TRACE or DELETE if those are not intended.

Tools

  • Nikto: Scans for common misconfigurations
  • OWASP ZAP: Checks security headers and CORS
  • Shodan: Finds exposed services and default credentials

A06: Vulnerable and Outdated Components

Using components with known vulnerabilities is one of the easiest risks to mitigate and one of the most commonly ignored. This includes libraries, frameworks, databases, and OS packages.

Test Cases

Enumerate dependencies:

# Node.js
npm audit

<span class="hljs-comment"># Python
pip-audit

<span class="hljs-comment"># Java
mvn dependency-check:check

Check CVEs for discovered versions:

# Find the version of a library from HTTP headers or response bodies
curl -I https://app.example.com <span class="hljs-pipe">| grep -i server
curl -I https://app.example.com <span class="hljs-pipe">| grep -i x-powered-by

Then search the National Vulnerability Database (nvd.nist.gov) for known CVEs for that version.

Tools

  • OWASP Dependency-Check: Scans Java, .NET, JavaScript
  • Snyk: SaaS tool with GitHub integration
  • Trivy: Container and filesystem vulnerability scanner

A07: Identification and Authentication Failures

This covers broken authentication — weak passwords, credential stuffing, missing MFA, insecure session tokens, and flawed "remember me" implementations.

Test Cases

Session token entropy — Capture a session token and analyze its structure:

Set-Cookie: sessionId=dXNlcjoxMjM0NTY=; Path=/; HttpOnly

Base64-decode it. If it encodes predictable data like a user ID, the token is insecure.

Missing HttpOnly and Secure flags:

HTTP/1.1 200 OK
Set-Cookie: session=abc123; Path=/

Cookies without HttpOnly are accessible to JavaScript (XSS risk). Cookies without Secure are sent over HTTP.

Credential stuffing protection — Test whether the application allows rapid login attempts with different credential pairs without triggering lockout or CAPTCHA.


A08: Software and Data Integrity Failures

This category covers insecure deserialization, CI/CD pipeline attacks, and auto-update mechanisms that do not verify integrity. The Log4Shell vulnerability was partially an integrity failure — a library that blindly resolved remote content.

Test Cases

Insecure deserialization — Look for serialized objects in cookies, POST bodies, or headers:

Cookie: user=rO0ABXNyAA==

rO0AB is the base64-encoded Java serialized object header. Try substituting a known gadget chain payload.

Content Security Policy for subresource integrity:

<!-- Secure -->
<script src="https://cdn.example.com/lib.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>

<!-- Insecure - no integrity check -->
<script src="https://cdn.example.com/lib.js"></script>

Check whether third-party scripts include integrity attributes.


A09: Security Logging and Monitoring Failures

You cannot detect or respond to attacks if you are not logging them. This category covers insufficient logging, missing alerting, and logs that do not contain enough information to reconstruct an attack.

Test Cases

Trigger security events and verify logging:

  1. Attempt to log in with invalid credentials 10 times
  2. Access a resource you should not have access to
  3. Submit clearly malicious payloads (' OR 1=1 --)

Then check your SIEM or log management system. If these events did not generate alerts or are not visible in logs with IP, timestamp, and user ID, your logging is insufficient.

Log injection testing — Submit newline characters in input fields:

username=admin%0aINJECTED_LOG_LINE

If the injected line appears in logs, an attacker could forge log entries to cover their tracks.


A10: Server-Side Request Forgery (SSRF)

SSRF occurs when an application makes HTTP requests to a user-controlled URL. An attacker can use this to reach internal services, cloud metadata endpoints, or bypass firewalls.

Test Cases

Basic SSRF detection — Find any parameter that accepts a URL:

POST /api/fetch-preview HTTP/1.1
Host: app.example.com
Content-Type: application/json

{"url": "http://169.254.169.254/latest/meta-data/"}

The AWS metadata endpoint (169.254.169.254) returns IAM credentials if the server is running on EC2 and SSRF is present.

Blind SSRF — Use an out-of-band detection server:

{"url": "http://your-burpcollaborator.net/ssrf-test"}

If your Burp Collaborator or interactsh server receives a request, SSRF is confirmed even if the response is not returned to you.

Tools

  • Burp Suite Pro: Built-in Collaborator for blind SSRF detection
  • interactsh: Open-source alternative to Burp Collaborator
  • SSRF-Sheriff: Specialized SSRF testing tool

Putting It All Together: A Testing Workflow

A complete OWASP Top 10 assessment should follow this workflow:

  1. Reconnaissance: Map all endpoints, parameters, and authentication mechanisms
  2. Automated scanning: Run OWASP ZAP or Burp Suite active scanner against all discovered endpoints
  3. Manual verification: Confirm every automated finding by hand — scanners produce false positives
  4. Manual testing for logic flaws: Access control, insecure design, and SSRF often require manual testing
  5. Component analysis: Run dependency scanners against all package manifests
  6. Reporting: Document every finding with reproduction steps, impact, and a recommended fix

OWASP ZAP Quick Start

# Install ZAP
docker pull ghcr.io/zaproxy/zaproxy:stable

<span class="hljs-comment"># Run baseline scan
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
  -t https://app.example.com \
  -r zap-report.html

<span class="hljs-comment"># Run full active scan
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-full-scan.py \
  -t https://app.example.com \
  -r zap-full-report.html

Burp Suite Essentials

Burp Suite intercepts all traffic between your browser and the target. Configure your browser to use Burp as a proxy (127.0.0.1:8080), then:

  • Proxy > HTTP history: Review every request your application makes
  • Scanner: Right-click any request → "Scan" to run active checks
  • Repeater: Modify and replay requests manually
  • Intruder: Fuzz parameters with wordlists

Integrating OWASP Testing Into CI/CD

Security testing should not be a once-a-year activity. Integrate it into your pipeline:

# GitHub Actions example
security-scan:
  runs-on: ubuntu-latest
  steps:
    - name: Run OWASP ZAP
      uses: zaproxy/action-baseline@v0.10.0
      with:
        target: 'https://staging.example.com'
        fail_action: true
        rules_file_name: '.zap/rules.tsv'

For dependency scanning:

    - name: Run npm audit
      run: npm audit --audit-level=high

    - name: Run Snyk
      uses: snyk/actions/node@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

Summary

The OWASP Top 10 is a minimum baseline, not a ceiling. Testing against all 10 categories requires a combination of automated tools (ZAP, Burp, dependency scanners) and manual testing — especially for access control flaws, business logic issues, and SSRF. Build security testing into your CI/CD pipeline, run it against every release, and treat security findings with the same priority as functional bugs.

The most important thing is to start. Pick one category from this guide, test your application against it today, and build from there. A partially tested application is more secure than an untested one.

Read more