Intercepting Proxies

An intercepting proxy is a tool that sits between your browser and the web server and shows you every HTTP request and response as it passes: the method, the URL, the headers, the cookies and the body, not just the finished page. ZAP (Zed Attack Proxy), the free open-source proxy long known as OWASP ZAP, is the example in this lesson; other intercepting proxies work the same way under different menu names.

Because the traffic flows through it, the proxy can keep a searchable history of every message, pause (intercept) a request so you can change it before it reaches the server, and replay a past request with different values. A tester uses this to see what the server does when the client sends something the real app never would, such as another user's order id, a higher role or no session at all.

Why it matters

Many serious web defects live in what the server trusts. If the server assumes the browser will only send order ids that belong to the logged-in user, changing that id in the proxy can reveal broken access control, A01 in the OWASP Top 10:2025 from the previous lesson, in minutes. A disabled button, a hidden field and client-side validation are only suggestions to the browser; the proxy lets you test the server, which is where security has to hold.

For the tester, the proxy turns a vague worry into repeatable evidence: the exact request, the one value you changed and the response. That is a bug report a developer can act on, and the history shows precisely what you sent, so you can show that an authorised test stayed inside its limits.

Where the proxy sits, and how to set it up safely

The proxy listens on a local address, for example 127.0.0.1:8080. You point a browser at it, and every request now travels browser to proxy to server, with each response coming back the same way. Unlike the DevTools Network panel, which records what one tab did, the proxy stands in the path and can hold a message before the server sees it.

Two set-up steps keep this safe. First, use a dedicated test browser profile, or a separate browser, that sends its traffic to the proxy, so your everyday logins and cookies never pass through it. Second, to read HTTPS the proxy ends the browser's encrypted connection itself and presents a certificate for each site, signed by its own certificate authority (CA). Trust that proxy CA in the test profile only, never system-wide or on a personal device, because a browser that trusts it accepts any certificate signed with its key, for any site. Remove it when the engagement ends.

A test-browser request meets the proxy's scope check first; only in-scope traffic is shown in history and passively scanned, and only it may be paused to change one id, role or session value, or replayed to the authorised target.
  1. 1Test browserall traffic → proxyA dedicated profile that trusts the proxy CA certificate
  2. 2Scope checkIs this host on the authorised list?Proxy

    Branch: Out of scope → passed on untouched: not intercepted, replayed or scannedCaution

    Gate: in scope only

  3. 3HistoryA searchable record of each request and response; passive scanning reads itProxy
  4. 4Intercept and modifyPause it and change one id, role or session valueGET /api/orders/1043Optional
  5. 5Authorised targetResponds; the response returns through the proxy into history

Throughout steps 3–5 Inside the authorised scope · written permission names these hosts

Back to step 3 Replay: resend from history with one value changed

Try it: HTTP Request Inspector

History, intercept-and-modify, and replay

The history (the History tab in ZAP; some tools call it HTTP history) lists every request and response, with filters such as method, status code and a URL pattern that matches one host, so you can find the one call you need among hundreds. Intercept-and-modify pauses a request at the proxy: you edit a header, a parameter or the body, then let it continue, so the server receives your version, not the browser's.

Replay sends a request from the history again with one value changed, so you can compare responses; in ZAP you right-click it and choose "Open/Resend with Request Editor". Replay turns "the button is greyed out" into a fact about the server. Three replays cover most first checks:

  • Changed id: keep your own session and ask for another user's order or profile. The server should refuse.
  • Changed role: resend, with a normal user's session, a request that only an admin should make, or set a role field from user to admin when updating your own test account. The server should refuse or ignore it.
  • Changed session value: remove the session cookie, or reuse one you have logged out of. The server should answer 401 Unauthorized or send you to log in, never return the data.

Try it: HTTP Headers Parser Try it: API Authentication Tester

Passive scanning: a lead, not a verdict

While traffic flows through it, the proxy can inspect each message and raise alerts without sending anything of its own. This is passive scanning, and because it only reads traffic you were already exchanging, it is safe to leave on during ordinary testing.

An alert is a lead, not a verdict: it can be a false positive, and passive scanning misses anything that needs a request the app never made. Confirm each alert by hand before reporting it. Active scanning, where the tool sends its own crafted attack requests, is a separate, higher-risk mode that needs explicit authorisation and is beyond this lesson.

  • Missing header: a response without Strict-Transport-Security or Content-Security-Policy.
  • Weak cookie: a session cookie set without the Secure or HttpOnly attribute (RFC 6265).
  • Leak: a token in a URL query string, or an error page that shows a stack trace.

Try it: Security Header Analyzer Try it: Cookie Analyzer

Scope and written authorisation come first

Scope is the exact set of hosts and paths you may test. In the proxy you mark only those as in scope, show only in-scope messages in the history, and limit intercept, replay and scanning to them. In ZAP you add the target to a context marked In Scope, can switch to protected mode, which blocks potentially dangerous actions such as intercepting, resending and active scanning outside the scope, and can set the passive scanner to scan only in-scope messages. The browser's other traffic, such as an analytics host or a third-party widget, usually still flows through the proxy; scope is what keeps you from changing or scanning it.

Authorisation is written permission from the system's owner that names the targets, the dates and what you may do. Test only systems you own or have explicit written permission to test; being a customer of a site is not permission. A proxy sends real, modified requests to a real server, and doing that without authorisation is not QA and is illegal in many countries. When in doubt, stop and ask.

Worked example: an access-control check by replay

You are authorised, in writing, to test your team's staging shop, and staging.shop.example is in the proxy scope. Logged in as your own test user, you open one of your orders and find its request in the history. In the request editor you change only the order id to one owned by a second test user, keep your own session cookie, and resend.

The secure result is 403 Forbidden or 404 Not Found: the server checks that the order belongs to the caller. A 200 OK with the other user's order is broken access control, an insecure direct object reference (IDOR), and you already hold the exact request and response for the bug report.

GET /api/orders/1042 HTTP/1.1
Host: staging.shop.example
Cookie: session=<your own test session>

# Replay with one change: an order id that is not yours
GET /api/orders/1043 HTTP/1.1
Host: staging.shop.example
Cookie: session=<your own test session>

# Secure response:   403 Forbidden  or  404 Not Found
# Broken access control: 200 OK with another user's order

Try it: API Request Builder

Common mistakes

  • Testing through your everyday browser profile, so personal logins and cookies end up in the capture and in screenshots.
  • Trusting the proxy CA system-wide or on a personal device, then forgetting to remove it.
  • Taking a greyed-out button or client-side validation as proof of a control instead of replaying the request to the server.
  • Leaving the scope open, so replay or scanning can reach hosts you have no permission to test.
  • Reporting a passive-scan alert as a confirmed defect without checking it by hand.
  • Changing two values at once, or not saving the exact request and response, so nobody can tell what caused the result.

The QA perspective

On a team, the intercepting proxy is a functional tester's tool as much as a specialist's. You use it in ordinary feature testing to see the requests behind a flow, reproduce a bug exactly, and run the few access-control checks every authenticated feature deserves: can I reach another user's record, can I act above my role, does the server check the session on every request. Deeper and active testing belongs with security specialists and the OWASP Web Security Testing Guide.

Agree scope and authorisation with the environment owner first, prefer staging to production, and use only the test accounts you were given. In the bug report, include the request and response with secrets masked, the one value you changed and the expected secure behaviour, so a developer can confirm the fix with the same replay.

Practice exercise

Plan a role check and a session check by replay

Your task

You are authorised, in writing, to test your team's staging shop, and its host is in the proxy scope. The material shows a request captured while your admin test user opened the user list, and the session cookie of your customer test user.

Plan two replays: one that tests the role check and one that tests the session check. For each, say what you change, what you keep and the expected secure response, then say what you confirm before sending.

Material
# Captured as your admin test user
GET /api/admin/users HTTP/1.1
Host: staging.shop.example
Cookie: session=a91e...   (admin test user)
Accept: application/json

# Session cookie of your customer test user
Cookie: session=7c03...
Steps
  1. Find the value that tells the server who is calling.
  2. Plan the role replay: what you swap and what stays as captured.
  3. Plan the session replay: what you remove and what stays as captured.
  4. List what you confirm before sending anything.
Show the model answer
Model answer

Both replays change only the session cookie: it is the only value here that tells the server who is calling, and the server works out the user and role from that session. The method, path and other headers stay exactly as captured, so any change in the response comes from that one value.

Role replay: replace a91e... with the customer session 7c03... and resend. Secure: 403 Forbidden, or 404 Not Found if the app hides admin routes. A 200 OK with the user list means a customer can act as an admin, which is broken access control.

Session replay: remove the Cookie header and resend. Secure: 401 Unauthorized or a redirect to the login page. A 200 OK with data means the endpoint does not check authentication at all.

Before sending, confirm that the host is in the proxy scope, that your written authorisation covers this host, this date and this kind of check, and that both accounts are test accounts you were given. Starting with GET helps: RFC 9110 defines it as a safe method, so a replay should not change data. If anything is unclear, stop and ask.

Frequently asked questions

Is an intercepting proxy the same as browser DevTools?

They overlap. The DevTools Network panel shows a tab's requests and lets you copy or resend some of them, which is enough for many checks. A proxy adds a true intercept step that holds the request before it reaches the server, one history across tabs and clients, and passive scanning, and it can capture non-browser clients such as a mobile app or curl. Start with DevTools; use a proxy when you need to change a request in flight or capture more than one client.

Why do I have to install a certificate?

HTTPS encrypts traffic between browser and server, so to read and change it the proxy ends the browser's connection itself and presents a certificate signed by its own CA. Your test browser accepts that only if it trusts the proxy CA. Install it in a dedicated test profile, never system-wide or on a personal device, and remove it when you are done.

Can I use a proxy on any website I want to test?

No. Use it only on systems you own or have explicit written permission to test. The proxy sends real, modified requests to a real server, and doing that without authorisation is not testing and is illegal in many countries. Set the proxy scope to the authorised hosts and leave everything else out.

What is the difference between passive and active scanning?

Passive scanning only reads the traffic you were already sending and receiving, so it is safe to leave on. Active scanning sends crafted requests of its own to probe for weaknesses; it is higher risk, can change data, and needs explicit authorisation. This lesson stays with passive scanning and manual, one-request-at-a-time checks.

References

Practise with Mutqan tools

Compose and send HTTP requests (method, URL, headers, auth, body) and inspect the response — a lightweight Postman in your browser.

API Testing

Test Bearer, Basic, API-key and custom-header authentication against an endpoint and compare authorised vs unauthorised responses.

API Testing

Parse raw HTTP request/response headers into a structured table with explanations.

Web

Parse Set-Cookie headers and check Secure, HttpOnly, SameSite, Domain, Path, expiry and size best practices.

Validation

Grade HTTP security headers (CSP, HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy, COOP/CORP) from pasted headers or a public URL.

Validation

See exactly what your client sends: method, headers, query, body, IP and TLS info.

API Testing

Go deeper

Your progress on this topic

Part of the QA Roadmap