Skip to content
cctbp
Go back

The Local Lab Blueprint: Building an Isolated, Scriptable Interception Lab

cctbp.com | Tom Stacy, CISSP®


Before you can find the seam in an authentication flow, you need to see the flow clearly. That means a lab that gives you deterministic results every time — no shared browser state, no ambient noise, no accidental leakage to live environments. This post is the foundation setup for everything else in this series.

The architecture here is deliberately minimal: Docker for containerization, mitmproxy for interception, Firefox Multi-Account Containers for browser-level session isolation. FOSS throughout, nothing exotic. The payoff is a lab you can tear down, wipe, and rebuild from scratch in under five minutes.


The Setup

The core problem with ad hoc interception labs is state contamination. Your regular browser profile bleeds cookies into test sessions. Your OS-level proxy config leaks across unrelated tabs. A hand-configured VM breaks after an update and takes an afternoon to restore. None of that is acceptable when you’re trying to reproduce an auth-flow edge case reliably.

The architecture draws a hard boundary around the testing environment at two levels:

The proxy sits in the middle. The isolated browser talks through it. The target — a local, containerized vulnerable app — sits at the end. Nothing touches live infrastructure.

[ Isolated Browser / Container ]

               ▼ (Proxy on Port 8080)
   [ Intercepting Proxy ]   <-- mitmweb / mitmproxy / mitmdump


       [ Target Server ]

The Seam

The seam in most ad hoc lab setups is the boundary between your research environment and everything else on your machine. The failure modes are predictable: a test session’s cookies end up in your regular browser, a proxy config change affects traffic you didn’t intend to intercept, or a log file captures a token that survives a lab teardown.

Docker eliminates the infrastructure drift problem. Browser containers eliminate the session bleed problem. Explicit proxy-per-container configuration keeps the intercept surface bounded.

The second seam is signal-to-noise. Auth flows are already multi-step redirect chains. If your proxy is catching browser telemetry, analytics pings, and system update checks alongside the flows you care about, you’ll miss things. Noise reduction is not optional.


Reproducing It

Prerequisites

Step 1: Inject the Proxy’s Root CA

mitmproxy generates its CA on first run at ~/.mitmproxy/mitmproxy-ca-cert.pem. Run it once to generate, then install:

# Run mitmproxy once to generate the CA, then Ctrl-C
mitmweb

# Copy the CA cert to the Debian trust store
sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem \
  /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt

# Update the trust store
sudo update-ca-certificates

Verify it registered:

grep -r "mitmproxy" /etc/ssl/certs/

Step 2: Write an Auth Logger Addon

mitmproxy’s Python addon API makes deterministic traffic manipulation trivial. This addon logs intercepted authorization tokens at the request hook — read-only by design. The same hook is where you’d add mutation logic for active token rewriting:

import logging
from mitmproxy import http

class AuthLogger:
    def request(self, flow: http.HTTPFlow) -> None:
        if "Authorization" in flow.request.headers:
            token = flow.request.headers["Authorization"]
            # Log only a prefix — never write full tokens to disk
            logging.info(f"[AUTH LOG] Intercepted token: {token[:20]}...")

addons = [
    AuthLogger()
]

Save as auth_logger.py.

Step 3: Run the Proxy

For interactive auth-flow analysis, mitmweb is the right interface. It renders the full redirect chain in a clickable flow list, toggles intercept mode without leaving the browser, and lets you edit and replay any request in place.

mitmweb -s auth_logger.py

Proxy listener: 127.0.0.1:8080. The web UI opens automatically in your default browser.

When you’re ready to automate the same checks headlessly — batch runs, CI integration, scripted regression — point the same addon at mitmdump:

mitmdump -p 8080 -s auth_logger.py

Same core engine, no UI overhead. The three interfaces (mitmproxy TUI, mitmweb, mitmdump) share an identical addon API, so addons are portable across all three without modification.

Step 4: Silence Background Noise

mitmproxy filter expressions use the ~u operator to match against URL patterns via regex. Add these to your startup config or as intercept filters in mitmweb to drop traffic you don’t care about:

~u "telemetry|analytics|update|safebrowsing|ocsp"

Set them as ignore patterns so matched flows are passed through without appearing in the flow list:

mitmweb -s auth_logger.py \
  --ignore-hosts ".*telemetry.*|.*analytics.*|.*safebrowsing.*"

The result is a clean flow list showing only the auth-relevant traffic.

Step 5: Configure Browser Session Containers

Firefox Multi-Account Containers gives you entirely independent cookie jars, cache domains, and local storage per container. For auth research, this means you can run Admin and User roles side-by-side in separate tabs without any state bleed between them.

Per-container proxy configuration (the key capability) lives under each container’s Advanced Proxy Settings. Route the container directly to 127.0.0.1:8080:

Tab A (Admin container) and Tab B (User container) are now independent authentication contexts, both feeding through the same mitmproxy listener. You’ll see each flow labeled with its origin if you tag them in the addon.

Step 6: Stand Up a Local Target

Rather than pointing your proxy at live production targets, spin up a local vulnerable app. A minimal containerized token-validation service that accepts alg:none JWTs gives you an immediate, risk-free environment to test JWT vulnerabilities, signature bypasses, and session-state mechanics without touching anything real.

Example docker-compose.yml for a Flask-based target:

version: "3.8"
services:
  target:
    build: ./target
    ports:
      - "8000:8000"
    environment:
      - ACCEPT_ALG_NONE=true

The entire stack — proxy, addon, vulnerable target — is now declarative. docker compose up puts the target online. mitmweb -s auth_logger.py puts the proxy in the path. Teardown is docker compose down and pkill mitmweb. From scratch to running lab in under five minutes.


Defender Perspective

This lab architecture mirrors what a well-instrumented production environment should look like from a logging perspective. Every request that passes through mitmproxy is a structured, inspectable event — the same property you want from your production proxy or WAF logs.

What this setup makes visible:

For blue teamers evaluating their own logging fidelity: if you can’t reconstruct a full OAuth authorization code flow from your proxy logs — authorization request, redirect, code exchange, token issuance — your log coverage is insufficient for detecting authorization code interception.


Takeaway

For red teamers: The lab is infrastructure, not a technique. Set it up once properly and every subsequent scenario runs against a known baseline. The containerized teardown-and-rebuild property is the critical one — it means you can verify a finding from scratch, on demand, without any “it worked yesterday” ambiguity. The same architecture scales to more complex multi-IDP flows without modification; you add containers, not complexity.

For defenders: The noise reduction and session isolation techniques here are directly applicable to your production monitoring setup. If your WAF or reverse proxy isn’t filtering auth-relevant traffic from background noise before it hits your SIEM, your detection rules are working harder than they need to. The signal you want is clean before it reaches detection logic, not after.


🚀 Looking to scale past local setups? If you’re testing distributed authentication architectures and need an automated, cloud-hosted platform for authorized OAuth, SAML, and OIDC interception without the local infrastructure overhead, join the ShroudCloud waitlist.


Tom Stacy, CISSP®, is an authentication and identity security specialist. He writes at cctbp.com and is building ShroudCloud™, an engagement infrastructure for auth and session security.


Share this post on:

Next Post
OAuth Authorization Code Interception: The Flow, the Seam, and What Your Logs Actually Show