Web Application Security Audit
Overview
A structured penetration testing methodology based on *The Web Application Hacker's Handbook*. Guides you through 10 sequential phases to systematically identify vulnerabilities in any web application you're building or reviewing.
When to Use
- Before deploying a web application to production
- When adding authentication, payment processing, or user-facing features
- During periodic security reviews
- After integrating third-party services or APIs
- When you suspect a specific vulnerability class but want comprehensive coverage
When NOT to Use
- Against applications you don't own or have authorization to test
- As a replacement for professional penetration testing on critical systems
- For network-level security (this is application-layer focused)
Process
Work through each phase sequentially. At each phase:
- Ask targeted questions about the specific application
- Read the relevant chapter summary from
cybersecurity/web-application-hackers-handbook/for detailed guidance - Suggest and execute concrete tests (grep patterns in source code, curl commands, Burp Suite steps, automated scripts)
- Flag findings with severity:
CRITICAL/HIGH/MEDIUM/LOW/INFO - Summarize findings before moving to the next phase
If the application doesn't have a relevant surface for a phase (e.g., no file uploads), acknowledge and skip with rationale.
digraph audit_phases {
rankdir=TB;
node [shape=box, style=rounded];
p1 [label="Phase 1\nMap the Application"];
p2 [label="Phase 2\nAnalyze the Application"];
p3 [label="Phase 3\nClient-Side Controls"];
p4 [label="Phase 4\nAuthentication"];
p5 [label="Phase 5\nSession Management"];
p6 [label="Phase 6\nAccess Controls"];
p7 [label="Phase 7\nInjection Vulnerabilities"];
p8 [label="Phase 8\nApplication Logic"];
p9 [label="Phase 9\nApplication Server"];
p10 [label="Phase 10\nReview & Report"];
report [label="Security Audit\nReport", shape=note];
p1 -> p2 -> p3 -> p4 -> p5 -> p6 -> p7 -> p8 -> p9 -> p10 -> report;
}Phase 1: Map the Application
Reference: cybersecurity/web-application-hackers-handbook/ch04-mapping-the-application.md
Goal: Discover the full attack surface before testing anything.
Questions to ask:
- What is the application's tech stack? (framework, language, database, hosting)
- What are all the routes/endpoints? (read route files, API definitions, OpenAPI specs)
- Are there admin panels, API docs, or debug endpoints?
- What third-party services are integrated?
Tests to run:
- Enumerate all routes from source code:
# Express.js grep -rn "app\.\(get\|post\|put\|delete\|patch\)" --include="*.ts" --include="*.js" # Django grep -rn "path\|url(" --include="*.py" urls.py # Rails grep -rn "get\|post\|put\|delete\|patch\|resources\|resource" config/routes.rb # Next.js — check app/ and pages/ directory structure - Check for exposed files:
robots.txt,sitemap.xml,.env,.git/,package.json - Search for hardcoded secrets in source:
grep -rni "password\|secret\|api_key\|token\|private_key" --include="*.ts" --include="*.js" --include="*.py" --include="*.env*" - Review HTML/JS comments for sensitive information
- Identify all input vectors: URL params, POST bodies, cookies, headers, file uploads, WebSockets
Deliverable: Complete attack surface map — routes, parameters, technologies, entry points.
Phase 2: Analyze the Application
Reference: cybersecurity/web-application-hackers-handbook/ch03-web-application-technologies.md
Goal: Understand what the application does and identify high-risk areas.
Questions to ask:
- What are the core business functions? (user management, payments, data CRUD, search, file handling)
- Which functions handle sensitive data? (PII, financial, credentials)
- Are there multi-step processes? (checkout, registration, approval workflows)
- What user roles exist? What can each role do?
Prioritize testing areas (highest risk first):
- Authentication and credential handling
- Payment/financial transaction processing
- File upload functionality
- Administrative interfaces
- API endpoints (often have weaker controls than web UI)
- Search functionality (frequent injection target)
- User-to-user features (stored XSS vector)
- Data export/import (injection, XXE)
Deliverable: Functional map with risk-prioritized areas of interest.
Phase 3: Test Client-Side Controls
Reference: cybersecurity/web-application-hackers-handbook/ch05-bypassing-client-side-controls.md
Goal: Verify the server never trusts client-side validation or state.
Questions to ask:
- Are there hidden form fields the server relies on? (prices, roles, user IDs)
- Is input validation only done client-side? (JavaScript, HTML5 attributes)
- Does the client transmit data that should be server-side state? (cart totals, discount flags, permission levels)
Tests to run:
- Search for hidden fields:
grep -rn 'type="hidden"\|type=.hidden.' --include="*.html" --include="*.tsx" --include="*.jsx" - Search for client-only validation:
grep -rn "maxlength\|pattern=\|required\b" --include="*.html" --include="*.tsx" --include="*.jsx" - Check if server-side validation mirrors client-side:
grep -rn "validate\|sanitize\|zod\|yup\|joi\|class-validator" --include="*.ts" --include="*.js" --include="*.py" - For each form, submit requests with: missing required fields, values exceeding maxlength, values violating patterns, modified hidden fields
- Test price/role/permission manipulation by modifying request bodies
Finding template:
[SEVERITY] Client-Side Control Bypass: [description]
Affected: [endpoint/parameter]
Test: [what you did]
Result: [what happened]
Impact: [what an attacker could achieve]
Fix: [server-side validation recommendation]Phase 4: Test Authentication
Reference: cybersecurity/web-application-hackers-handbook/ch06-attacking-authentication.md
Goal: Verify authentication cannot be bypassed, brute-forced, or abused.
Tests to run:
Username enumeration:
- Compare responses for valid vs invalid usernames on login, registration, and password reset
- Check response body, status codes, timing differences, and response length
- Search for inconsistent error messages:
grep -rn "invalid.*username\|user.*not found\|no.*account\|incorrect.*password" --include="*.ts" --include="*.js" --include="*.py"
Brute-force resilience:
- Check for account lockout, rate limiting, CAPTCHA
- Search for rate limiting implementation:
grep -rn "rate.limit\|throttle\|brute\|lockout\|max.*attempts" --include="*.ts" --include="*.js" --include="*.py"
Password policy:
- Test minimum length, complexity requirements, common password blocking
- Check password storage:
grep -rn "bcrypt\|argon2\|scrypt\|pbkdf2\|sha256\|sha1\|md5\|plaintext" --include="*.ts" --include="*.js" --include="*.py" CRITICALif passwords stored as plaintext, MD5, or SHA1 without salt
Password reset:
- Check token randomness, expiry, single-use enforcement
- Check if reset tokens are in URLs (logged in server logs, browser history)
Multi-factor authentication:
- Can MFA step be skipped by directly requesting authenticated endpoints?
- Can MFA be bypassed by replaying codes or using expired codes?
Remember me:
- Decode the remember-me token (Base64, JWT) — does it contain user info?
- Is it invalidated on password change?
Phase 5: Test Session Management
Reference: cybersecurity/web-application-hackers-handbook/ch07-attacking-session-management.md
Goal: Verify sessions cannot be hijacked, fixated, or predicted.
Tests to run:
Token generation:
- Collect multiple session tokens and check for patterns (sequential, timestamp-based, low entropy)
- Decode tokens (Base64, JWT) — do they contain sensitive data?
# For JWTs grep -rn "jwt\|jsonwebtoken\|jose" --include="*.ts" --include="*.js" --include="*.py"
Cookie flags:
- Check every cookie for:
Secure,HttpOnly,SameSite,Domain,Pathgrep -rn "Set-Cookie\|cookie\|setCookie\|httpOnly\|secure\|sameSite" --include="*.ts" --include="*.js" --include="*.py" HIGHif session cookie missingHttpOnly(XSS can steal it)HIGHif session cookie missingSecure(transmitted over HTTP)MEDIUMif session cookie missingSameSite(CSRF vector)
Session lifecycle:
- Does the token change after login? (session fixation if not)
- Is the session invalidated server-side on logout? (not just cookie deletion)
- Is there idle timeout and absolute timeout?
CSRF protection:
- Identify all state-changing operations (POST/PUT/DELETE)
- Check for anti-CSRF tokens:
grep -rn "csrf\|xsrf\|_token\|csrfmiddleware" --include="*.ts" --include="*.js" --include="*.py" --include="*.html" - Can state-changing requests succeed without the CSRF token?
Phase 6: Test Access Controls
Reference: cybersecurity/web-application-hackers-handbook/ch08-attacking-access-controls.md
Goal: Verify users cannot access unauthorized data or functionality.
Questions to ask:
- What user roles exist? (admin, user, moderator, API consumer)
- How is authorization enforced? (middleware, decorators, inline checks)
- Are there resource IDs in URLs or request bodies that could be manipulated?
Tests to run:
IDOR (Insecure Direct Object Reference):
- Find all endpoints with resource IDs:
grep -rn "/users/\|/orders/\|/documents/\|/api/.*/:id\|/api/.*/<.*>" --include="*.ts" --include="*.js" --include="*.py" - As User A, request User B's resources by changing IDs
CRITICALif successful
Vertical privilege escalation:
- As a regular user, request admin endpoints directly
- Check if authorization is enforced per-endpoint:
grep -rn "isAdmin\|requireAdmin\|role.*admin\|authorize\|permission\|@Roles\|@RequiresRole" --include="*.ts" --include="*.js" --include="*.py" - Check if any endpoints lack authorization middleware
Horizontal privilege escalation:
- Modify user-identifying parameters (
user_id,account_id,email) in requests - Check if the server validates that the requested resource belongs to the authenticated user
Multi-step process controls:
- For multi-step flows (checkout, approval), test skipping to later steps directly
- Test performing steps out of order
Phase 7: Test for Injection Vulnerabilities
Reference: cybersecurity/web-application-hackers-handbook/ch09-attacking-data-stores.md, ch10-attacking-back-end-components.md, ch12-attacking-users-xss.md
Goal: Verify all input is safely handled across every context.
SQL Injection:
# Find raw query construction (CRITICAL pattern)
grep -rn "query.*+\|execute.*+\|raw.*+\|\\.format.*SELECT\|f\".*SELECT\|f'.*SELECT" --include="*.ts" --include="*.js" --include="*.py"
# Verify parameterized queries are used
grep -rn "prepare\|parameterized\|\$[0-9]\|placeholder\|\?" --include="*.ts" --include="*.js" --include="*.py"CRITICALif string concatenation/interpolation used in SQL queries
XSS (Cross-Site Scripting):
# Find dangerous DOM operations
grep -rn "innerHTML\|outerHTML\|document\.write\|\.html(\|dangerouslySetInnerHTML\|v-html\|\{!! " --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.vue" --include="*.blade.php"
# Find eval usage
grep -rn "eval(\|Function(\|setTimeout.*string\|setInterval.*string" --include="*.ts" --include="*.js"HIGHfor stored XSS,MEDIUMfor reflected XSS,MEDIUMfor DOM-based XSS
OS Command Injection:
grep -rn "exec(\|execSync\|spawn(\|system(\|popen\|subprocess\|child_process\|shell_exec\|passthru\|backtick" --include="*.ts" --include="*.js" --include="*.py" --include="*.php"CRITICALif user input flows into command execution
Path Traversal:
grep -rn "readFile\|writeFile\|createReadStream\|open(\|path\.join.*req\|path\.resolve.*req\|fs\." --include="*.ts" --include="*.js" --include="*.py"- Check if user input is used in file paths without sanitization
XXE (XML External Entity):
grep -rn "parseXML\|DOMParser\|SAXParser\|XMLReader\|etree\.parse\|xml2js\|libxml" --include="*.ts" --include="*.js" --include="*.py"- Check if external entity processing is disabled
SSRF (Server-Side Request Forgery):
grep -rn "fetch(\|axios\|request(\|urllib\|http\.get\|https\.get\|curl\|wget" --include="*.ts" --include="*.js" --include="*.py"- Check if user-supplied URLs are validated against an allowlist
CRITICALif user input flows directly into server-side HTTP requests without validation
Server-Side Template Injection (SSTI):
grep -rn "render_template_string\|Template(\|Jinja2\|nunjucks.*render\|handlebars.*compile\|ejs.*render" --include="*.ts" --include="*.js" --include="*.py"- Check if user input is embedded in templates before rendering
Phase 8: Test Application Logic
Reference: cybersecurity/web-application-hackers-handbook/ch11-attacking-application-logic.md
Goal: Identify flaws in business logic that automated scanners cannot find.
Questions to ask:
- What assumptions does each function make about user behavior?
- Are there multi-step processes? Can steps be skipped or reordered?
- Are there financial transactions? Can amounts be manipulated (negative values, zero, overflow)?
- Are there referral/reward/coupon systems? Can they be abused?
Tests to run:
Race conditions:
grep -rn "balance\|credits\|quantity\|stock\|inventory\|coupon\|redeem\|transfer\|withdraw" --include="*.ts" --include="*.js" --include="*.py"- For any check-then-act pattern (check balance → deduct), test concurrent requests
HIGHif double-spending or double-redemption is possible
Multi-step process abuse:
- Map every multi-step flow (checkout, registration, approval)
- Test: skip steps, repeat steps, go backward, change data between steps, switch user context between steps
Transaction logic:
- Test negative amounts, zero amounts, extremely large amounts
- Test fractional values where integers expected
- Test self-referral, circular referral chains
Input normalization conflicts:
- Test unicode normalization issues (different representations of same character)
- Test case sensitivity conflicts (register as "Admin" when "admin" exists)
Phase 9: Test Application Server
Reference: cybersecurity/web-application-hackers-handbook/ch18-attacking-the-application-server.md
Goal: Verify the server platform itself is hardened.
Tests to run:
Default credentials:
- Check if admin panels exist at common paths:
/admin,/wp-admin,/phpmyadmin,/console,/manager - Test default credentials for any discovered admin interfaces
Dangerous HTTP methods:
curl -X OPTIONS <target-url> -iMEDIUMif PUT, DELETE, or TRACE are enabled unnecessarily
Security headers:
curl -s -I <target-url>Check for:
Content-Security-Policy—HIGHif missing (XSS mitigation)Strict-Transport-Security—HIGHif missing (HTTPS enforcement)X-Frame-Optionsor CSPframe-ancestors—MEDIUMif missing (clickjacking)X-Content-Type-Options: nosniff—LOWif missing (MIME sniffing)Referrer-Policy—LOWif missing (information leakage)Permissions-Policy—INFOif missingServer/X-Powered-By—INFOif present (version disclosure)
Debug mode:
grep -rn "DEBUG.*=.*True\|debug.*:.*true\|NODE_ENV.*development\|FLASK_DEBUG\|DJANGO_DEBUG" --include="*.py" --include="*.js" --include="*.ts" --include="*.env*" --include="*.yaml" --include="*.yml"HIGHif debug mode enabled in production config
Dependency vulnerabilities:
# Node.js
npm audit
# Python
pip-audit # or safety check
# Ruby
bundle auditKnown CVEs:
- Check framework/library versions against known vulnerabilities
CRITICALfor RCE CVEs,HIGHfor auth bypass CVEs
Phase 10: Review & Report
Reference: cybersecurity/web-application-hackers-handbook/ch15-exploiting-information-disclosure.md, ch21-web-application-hackers-methodology.md
Final checks:
Information disclosure:
grep -rn "console\.log\|print(\|logger\.\(debug\|info\)\|TODO\|FIXME\|HACK\|XXX" --include="*.ts" --include="*.js" --include="*.py"- Check for verbose error messages exposing internals
- Check for exposed
.git/,.env, source maps, backup files
SSL/TLS:
# If accessible externally
nmap --script ssl-enum-ciphers -p 443 <target>
# Or use testssl.shGenerate the audit report:
# Security Audit Report: [Application Name]
**Date:** [date]
**Auditor:** [name]
**Scope:** [what was tested]
## Executive Summary
[1-2 paragraph summary of overall security posture and critical findings]
## Findings Summary
| # | Severity | Finding | Phase |
|---|----------|---------|-------|
| 1 | CRITICAL | [title] | [phase] |
| 2 | HIGH | [title] | [phase] |
| ... | ... | ... | ... |
## Detailed Findings
### Finding 1: [Title]
**Severity:** CRITICAL / HIGH / MEDIUM / LOW / INFO
**Phase:** [which phase found it]
**Affected Component:** [endpoint, file, function]
**Description:**
[What the vulnerability is and why it exists]
**Reproduction Steps:**
1. [Step-by-step to reproduce]
**Impact:**
[What an attacker could achieve — data access, account takeover, RCE, etc.]
**Remediation:**
[Specific, actionable fix with code example if possible]
**Reference:**
[OWASP, CWE, or WAHH chapter reference]
---
[Repeat for each finding]
## Recommendations Priority
1. [Fix critical/high findings immediately]
2. [Fix medium findings before next release]
3. [Fix low/info findings as part of regular maintenance]
## Out of Scope / Not Tested
[What was explicitly excluded and why]Severity Rating Guide
| Severity | Criteria | Examples |
|---|---|---|
| CRITICAL | Immediate exploitation, RCE, full data breach, auth bypass | SQL injection with data access, RCE via command injection, hardcoded admin credentials, unauthenticated admin access |
| HIGH | Significant data exposure, account takeover, privilege escalation | Stored XSS, IDOR on sensitive data, broken access controls, session fixation, missing HTTPS enforcement |
| MEDIUM | Limited exploitation, requires user interaction, partial data exposure | Reflected XSS, CSRF on non-critical functions, missing SameSite cookies, verbose error messages with internal paths |
| LOW | Minor information disclosure, best practice violation | Version disclosure in headers, missing X-Content-Type-Options, autocomplete on sensitive fields |
| INFO | Observation, no direct security impact | Missing Permissions-Policy, minor configuration notes, suggestions for defense-in-depth |
Common Mistakes
| Mistake | Fix |
|---|---|
| Testing only the happy path | Test every parameter with malicious input — injection lives in the edge cases |
| Skipping access control testing | IDOR is consistently a top vulnerability — test every resource endpoint with different user contexts |
| Only testing through the UI | The UI hides parameters, endpoints, and capabilities — test the API directly |
| Assuming the framework handles security | Frameworks provide tools, not guarantees — verify each mechanism is correctly configured and used |
| Testing in isolation | Chain findings — info disclosure + IDOR + XSS can escalate from LOW to CRITICAL |
| Stopping at first finding per category | One SQL injection doesn't mean all queries are vulnerable — test each endpoint independently |