// guides

Web Application Penetration Testing Methodology

Diagram-like scene of a web application penetration testing methodology across roles and objects

A web application penetration testing methodology is an authorized, manual pass over roles, objects, and workflows that ends in reproduced business impact, not a scanner PDF. DAST output is a triage list; the test is the mapping, the authorization matrix, the logic abuse, and the chain.

The short answer

  • A senior web app pentest scopes the system, maps every role and workflow, then tests authentication, authorization, business logic, and input handling before chaining findings into proof.
  • OWASP WSTG, PTES, NIST SP 800-115, and OWASP ASVS describe different jobs: process, test cases, assessment planning, and verification requirements.
  • Scanner findings are leads. The deliverable is a reproducible report with business impact, a coverage matrix, and retest evidence.
  • Most high-value defects sit in object-level authorization and multi-step logic, which crawlers do not exercise.

Analyst desk mapping a web application penetration testing methodology across roles
The working artifact is a role-and-object matrix, not a URL dump.

Key takeaways

  • A web application penetration testing methodology is an authorized simulation of a stateful, role-based system. A DAST PDF is triage, not the deliverable.
  • PTES, NIST SP 800-115, OWASP WSTG, and OWASP ASVS do different jobs. Pin WSTG and ASVS editions before anyone quotes test cases or requirement IDs.
  • The working artifact is a role-and-object matrix: roles, object types, workflow states, and the read, update, delete, export, and approve actions on each cell.
  • Most high-value defects sit in object-level authorization (IDOR, BOLA, API1) and multi-step business logic. Crawlers do not exercise those paths.
  • APIs, GraphQL, WebSockets, uploads, and LLM or MCP features need their own checks. A scope line that says only "the website" drops them.
  • Judge the engagement on reproduced chains, named exclusions, and retest evidence. Finding count and raw CVSS do not measure coverage.

What is a web application penetration testing methodology?

A web application penetration testing methodology is a written sequence for simulating an attacker against a stateful, role-based system and stopping at safe proof of impact.

It is not a vulnerability scan, a vulnerability assessment, a bug bounty, or a red team. A penetration test is goal-directed and runs under written rules of engagement. A scan hunts signatures. An assessment triages those signatures. A bounty crowdsources individual bugs. A red team tests whether people and detection catch an objective across channels.

Buyers who collapse those words pay for breadth and receive a finding dump.

Engagement What you buy Evidence you should get Typical cadence
Penetration test Authorized attacker simulation against scoped apps and APIs Reproduced steps, chains, business impact, retest Per release or annual, plus material changes
Vulnerability scan (DAST) Crawl and known-signature coverage Candidate findings, many unvalidated Continuous or weekly
Vulnerability assessment Scan plus analyst triage Deduplicated, prioritized issues with less exploit depth Periodic
Bug bounty Crowd of researchers on a policy Individual reports of uneven depth Always on
Red team Objective across tech, people, and process Detection timeline and blast radius from a foothold Infrequent, objective-driven

Four references show up in statements of work, and they do different jobs. PTES splits the work into seven phases: pre-engagement, intelligence gathering, threat modeling, vulnerability analysis, exploitation, post-exploitation, and reporting. NIST SP 800-115 is the US government guide for planning, executing, and reporting technical tests.

The OWASP Web Security Testing Guide (WSTG) v4.2 is the web checklist most teams still open. It is commonly treated as twelve categories: information gathering, configuration, identity, authentication, authorization, session management, input validation, error handling, cryptography, business logic, client-side testing, and API testing. Confirm the current version and test-case count before a contract freezes that list.

OWASP ASVS is a verification baseline, not a test script. ASVS 4.0.3 remains widely cited. Later editions, including the ASVS 5.0 line, change requirement numbers. Pin the edition in the contract before anyone quotes an ID.

OWASP Top 10:2021 still frames what many buyers expect: Broken Access Control (A01), Injection (A03), Insecure Design (A04), Security Misconfiguration (A05), Identification and Authentication Failures (A07), and server-side request forgery (A10). Confirm whether your policy names a newer edition.

Once the app is mostly JSON, use the OWASP API Security Top 10:2023: Broken Object Level Authorization (API1), Broken Authentication (API2), Broken Object Property Level Authorization (API3), Unrestricted Resource Consumption (API4), Broken Function Level Authorization (API5), and Unrestricted Access to Sensitive Business Flows (API6).

Time on a serious engagement is uneven. An illustrative split, not a published benchmark, is about 20-30% mapping, 20-25% authentication and authorization, 15-20% business logic, 10-15% injection and client-side checks, and 15-20% chaining, reporting, and retest. If the timesheet is mostly payload spraying, the work stopped at the scanner.

How do scope and rules of engagement set the test?

Scope and rules of engagement decide which hosts, roles, data, and techniques are legal to touch, and what the report may claim.

Write the in-scope hosts, APIs, mobile backends, and admin panels. Write the out-of-scope third parties, payment processors, and production datasets. Name testing windows, rate limits, emergency contacts, evidence handling, and retention. Banned techniques usually include destructive deletes, denial of service, and phishing real customers.

Test accounts should exist for every role that matters: a low-privilege user, a peer in the same tenant, a user in another tenant, an admin, and a user who has not finished onboarding. Missing accounts become silent gaps in the matrix.

Black-box testing starts from a URL and public docs. It is realistic and slow, and it misses routes the UI never links. Gray-box adds accounts, role docs, and often an OpenAPI file. That is the default for a web application penetration testing engagement that has to cover authorization.

White-box adds source, configs, and identity wiring. It finds design flaws faster and is less of a surprise-attack simulation. Say which box you bought. Silent exclusions of tools, admin APIs, or SSO leave untested exactly the coverage the board thinks it paid for. The risk stays in the product.

Legal authorization is not a footer. In the United States the Computer Fraud and Abuse Act, in the UK the Computer Misuse Act, and in the EU Directive 2013/40/EU create criminal exposure for testing without permission. This is risk awareness, not legal advice; have counsel sign the authorization.

GDPR and the data-processing terms constrain how personal data in screenshots is stored. Redact secrets and customer records before the report leaves the test environment.

Production can be in scope, and it raises availability, integrity, and privacy risk. Staging often drifts: different WAF rules, empty tenants, fake SSO, missing webhooks. Prefer synthetic data and conservative techniques on production. Record every place staging is not production so residual risk has an owner.

PCI DSS 4.0 requirement 11 expects penetration testing of the cardholder data environment and segmentation checks. Confirm the current sub-requirement and cadence with your assessor before you copy a sentence into the rules of engagement.

How does a senior tester map what a crawler misses?

Mapping builds the real attack surface: authenticated routes, hidden APIs, roles, object types, and workflow states a crawler never requested.

Unauthenticated and authenticated crawls in Burp Suite or OWASP ZAP are the start. They are not the map. A modern front end hides routes inside JavaScript bundles and source maps. Wordlists in ffuf or Feroxbuster, plus Amass or Subfinder on external names, catch hosts the sitemap forgot.

Review robots.txt, sitemaps, and forgotten admin paths, then discard endpoints that only return a styled 404 page.

Pull OpenAPI or Swagger when it is exposed or handed over, and record the exact file you tested. Schema formats change often. Where GraphQL introspection is permitted, record types, mutations, and which role the schema claims may call them. Note WebSocket URLs, upload handlers, webhook receivers, and third-party widgets that post back to your origin.

Mobile apps often speak a fatter API than the website. If that API is yours, it belongs in scope even when the marketing site looks small.

The artifact that matters is a role-and-object matrix, not a flat URL list. Rows are roles: anonymous, user, peer, manager, support, admin, other tenant. Columns are object types (order, invoice, file, project, user) and states (draft, submitted, approved, refunded). Each cell is a planned action: read, update, delete, export, approve.

Coverage later means how many of those cells were exercised, not how many scanner templates returned a hit.

Threat modeling sits here, in the PTES sense: which data is worth stealing, which workflow moves money, and which integration holds a privileged token. That ranking decides where the remaining days go.

What is the difference between authentication and authorization testing?

Authentication proves who the caller is. Authorization decides what that caller may do. A working login says nothing about whether user A can read tenant B.

Authentication testing covers the identity front door: login, MFA and WebAuthn or FIDO2 enrollment, account recovery, password-reset tokens, remember-me cookies, session rotation on login, logout invalidation, concurrent sessions, and anti-automation. SSO belongs on this door: SAML 2.0, OpenID Connect, and OAuth 2.0. Failures here map to OWASP A07 and to API2, Broken Authentication.

Session review is the hinge. Cookies need Secure, HttpOnly, and a deliberate SameSite value. __Host- prefixes are a strong default when the app can use them. Check idle and absolute timeouts, fixation, token entropy, and whether server-side revocation actually kills the session.

JWT review checks signature validation, algorithm handling, key distribution, kid and jku or x5u behavior, and whether exp, aud, and iss are enforced. Authorization that trusts a client-supplied role claim is already broken.

OAuth and OpenID Connect review checks redirect_uri allowlists, state, PKCE, scope creep, mix-up, token leakage in logs or referrers, and whether access tokens are audience-bound and short-lived. SAML review checks XML signature validation, signature-wrapping weaknesses, audience and recipient restrictions, assertion replay, and parser quirks around comments.

Authorization testing starts after a valid session exists. It asks whether each role is held to the matrix: horizontal access between peers, vertical access into admin functions, and tenant boundaries. Teams that stop at “login works, MFA works, cookies look fine” have tested identity proofing and skipped permission enforcement. That gap is how BOLA reaches production.

IDOR and BOLA are the same family: object-level authorization failure, commonly CWE-639. The identifier might be a numeric id, a UUID, a filename, or a GraphQL global id. Predictability does not matter if the server never checks ownership. Broken access control and IDOR testing is where most web risk pays out, which is why OWASP still lists it as A01 and as API1.

BFLA is function-level failure: the support role can call an admin mutation, or a member can hit an export-all endpoint. That lines up with missing authorization (CWE-862) and incorrect authorization (CWE-863).

A practical pass uses two users in tenant A and one user in tenant B, plus a privileged role. For each object type, request read, update, delete, and export with the other user’s id, the other tenant’s id, and a removed member’s id. State matters: a draft someone else owns, an approved record that should be immutable, a soft-deleted file.

Mass assignment (CWE-915) sits next door. Compare fields the UI sends with fields the API accepts. Role, tenant_id, price, status, owner_id, and is_admin are the usual over-posted fields. Property-level authorization is API3: the object may be readable while a hidden field must not be writable.

GraphQL needs the same matrix at field and mutation level, not only at the HTTP route. One POST that returns 200 for everything hides BFLA from a naive crawler. Batching and aliases can slip past per-request limits. Treat that as both authorization and Unrestricted Resource Consumption testing.

Evidence is the pair of requests and the data that came back, with identifiers and personal data redacted. “The parameter looks sequential” is not a finding. “User A retrieved user B’s invoice PDF, and the server returned 200 with tenant B’s amount” is a finding.

Door versus hallway illustrating authentication versus authorization testing
A valid login only opens the door. Authorization is every room behind it.

How should logic, injection, APIs, and LLM features be tested?

Business logic testing walks the money and approval paths and tries to break rules the product claims to enforce. Scanners do not know that a coupon stacks once, that a refund cannot exceed the captured amount, or that step three requires step two.

Learn the domain from the product owner: pricing, inventory reservation, subscription changes, KYC gates, support overrides. Then make the tests specific. Change price, quantity, currency, or discount on a request the UI refused to send. Call a later step directly. Submit a negative quantity. Replay a completed checkout. Abuse an idempotency key so a retry doubles a credit. Push a limit one unit past the documented cap.

Race conditions are time-of-check versus time-of-use bugs: double redemption, coupon reuse, duplicate payout, inventory oversell. Authorized tests stay inside the agreed rate limit, use synthetic records, and stop at a safe proof, such as two ledger rows for one balance. HTTP/2 single-packet race techniques show up in research write-ups. They are not an excuse to stress production.

OWASP calls a slice of this Insecure Design (A04) and, on APIs, Unrestricted Access to Sensitive Business Flows (API6). Name the business rule, the request that violated it, and the money or data that moved. A note that a workflow “might be skippable” wastes the reader’s time.

Injection and client-side checks still belong, as a focused slice aimed at places frameworks and WAFs do not already close. That includes SQL injection, NoSQL and ORM mistakes, command injection, SSTI, XXE, SSRF, LDAP and XPath injection, insecure deserialization, prototype pollution, header injection, open redirect, and XSS. Raw queries in reporting jobs, shell calls in file processors, template engines in email builders, and XML parsers on upload still show up. Treat a WAF as a speed bump. Retest with the WAF in the mode production uses, and say so.

SSRF deserves a cloud-aware pass: server-side fetches toward internal names and metadata endpoints, plus designs that fetch arbitrary URLs. Defenses that hold are strict allowlists, metadata lock-down such as IMDSv2 where that is the control, and egress control. Confirm impact with a canary you control. Do not pivot through a customer’s cloud from a production finding.

Request smuggling and web cache poisoning depend on front-end and back-end parsing differences. Scanners flag candidates. Manual confirmation with a clear victim story is the finding. A desync screenshot with no cache impact is a lead.

Client-side work covers DOM XSS, CSP quality, postMessage origin checks, CORS that reflects arbitrary origins with credentials, clickjacking on sensitive actions, tokens in local or session storage, service workers, third-party scripts, and Subresource Integrity. CSRF still matters where cookie sessions change state without a real token or a SameSite barrier. These bugs are often medium alone. They become serious when chained to a session or an open redirect.

API penetration testing applies the role-and-object matrix to every operation, not a sample of REST paths. Contract checks and hand testing complement each other: the contract tool finds schema violations, the human finds authorization and price fields. GraphQL adds introspection exposure, depth and cost limits, batching and alias abuse, mutation authorization, and whether persisted queries are actually enforced.

WebSocket testing checks origin validation, authentication on the handshake, authorization on each message, replay, cross-site WebSocket hijacking, and rate limits. File upload testing checks content type, extension, and magic bytes, where bytes are stored, whether that origin can execute them, image-library attack surface, SVG active content, archive expansion, and authorization on the download URL.

LLM-backed features are a separate trust problem glued to the same session. Prompt injection, indirect injection through retrieved documents, tool abuse, excessive agency, and MCP permission boundaries do not show up in classic WSTG categories. Scope them on purpose: which tools the model can call, whose data retrieval can see, and whether a document can steer a tool. Treat that pass as its own workstream.

Our note on what a web pentest misses in AI components is the boundary. A web methodology that only fuzzes the chat box misses the tool chain. If the statement of work says “the website” and the product is an API with a thin UI plus an agent, the methodology is already wrong.

How do chains, the report, and coverage prove the test?

Chaining combines a small information leak, a weak token, or a logic gap with an authorization flaw until the path shows account or tenant impact, then stops.

An open redirect plus a loose OAuth redirect_uri check, a verbose error that leaks an object id plus a missing ownership check, or a low-privilege field that is mass-assignable into a role, can become account takeover or cross-tenant access. Each hop is documented with the request that proved it. The chain is one finding with a primary impact, plus supporting observations, not five mediums inflated for a dashboard.

Rules of engagement cap the demonstration. Prove you can read one synthetic record, or change one test user’s role in a way that reverts. Do not dump a tenant, move money, or persist a webshell. Post-exploitation in the PTES sense, for a web app, usually means what else this session unlocks inside the same application, not a network pivot, unless the rules say otherwise.

CVSS is a technical score, not the sort order. Sort by business impact: data exposed, money moved, accounts taken, tenants crossed. A high technical score on a dead feature can sit below a logic flaw the calculator calls medium.

What the report has to contain

  • Scope, rules of engagement, box type (black, gray, or white), and every exclusion with a risk owner.
  • The role-and-object matrix, with cells tested, cells blocked, and cells skipped.
  • Findings as reproduced requests and responses, secrets and personal data redacted, each tied to a business rule or control that failed.
  • Chains written as one impact, with the hops as evidence, plus remediation a developer can place in code: server-side checks, not a slogan to validate input.
  • Retest evidence after the fix, on the same requests, stating what still reproduces.

No honest methodology quotes a universal day count. The dossier of roles, object types, environments, SSO, and extra surfaces sets the calendar. A single app with a few roles is a short senior engagement. A multi-tenant product with SSO, a public API, GraphQL, and an agent feature multiplies the matrix. Ask for the day plan against that matrix. A flat SKU that prices only scanner hours is a scan.

Buyers measure quality by cells exercised, chains reproduced, exclusions named, and retest results. Finding count is a weak proxy. A report with twelve validated authorization breaks and a finished retest beats a PDF with two hundred unconfirmed scanner titles.

What buyers should demand before they sign

Demand the matrix, the accounts, and the retest clause in the statement of work, before the kickoff call. If those three are missing, you are buying a crawl.

Ask which WSTG version, which ASVS edition, and which Top 10 the team will cite, and where API, WebSocket, upload, and LLM surfaces sit relative to “the website.” Ask what fraction of senior time is reserved for authorization, logic, and chaining. The illustrative split above is a smell test, not a benchmark you can audit to the hour.

Hold the vendor to safe proof. Impact is a redacted request pair and a business consequence, inside the rate limit and the data rules you signed. That standard is what separates a penetration test from a vulnerability scan with a longer cover page.

Race on a checkout line as a metaphor for business logic vulnerability testing
Logic and race bugs live in the workflow, where crawlers do not shop.

FAQ

Why is a DAST scanner report not a penetration test?

A DAST run crawls what it can reach and matches known signatures. A penetration test validates those leads, then spends most of its time on authorization, business logic, and chains the scanner cannot infer. The deliverable is reproduced impact, a coverage matrix, and a retest, not an unvalidated finding list.

How do senior testers test IDOR, BOLA, and tenant isolation?

They use real sessions for two users in one tenant, a user in a second tenant, and a privileged role. For each object type and state they attempt read, update, delete, and export with another user's id and another tenant's id. A finding is the other tenant's data coming back, not a guess that an identifier looks sequential.

How long does a web application penetration test take?

There is no universal day count. Time tracks the role-and-object matrix, the number of environments, and whether SSO, public APIs, GraphQL, or LLM tools are in scope. Price the day plan against that matrix. An engagement whose timesheet is mostly automated payloads never left the scanner.

What should a web application penetration test report contain?

Scope and rules of engagement, the box type, exclusions with owners, the coverage matrix, redacted request-and-response proof, business impact, remediation a developer can implement, and retest results on the same requests. Chains should be one finding with a primary impact, not a stack of inflated mediums.

Which standard should the statement of work name?

Use them for different jobs. PTES for phases, NIST SP 800-115 for planning and reporting discipline, OWASP WSTG for web test categories, and OWASP ASVS for verification requirements. Name the WSTG version and the ASVS edition in the contract. OWASP Top 10:2021 and the API Security Top 10:2023 are the buyer-facing maps, after you confirm your policy's edition.

How should LLM-backed features sit inside a web app pentest?

Scope them as their own workstream on the same engagement, not as extra chat fuzzing. Record which tools the model can call, whose data retrieval can see, and whether untrusted documents can steer a tool call. Classic WSTG categories do not cover that permission boundary.

agent::offense runs this methodology by hand: role-and-object coverage, logic abuse, and chains with a retest, across web apps and the APIs behind them. If your last report was a scanner export, start with a scoped web application penetration testing engagement that names the matrix up front.



// get started

Work with AgentOffense

Tell us about your target and goals. We’ll reply with scope and a fixed-price quote — usually within one business day.

./request_engagement