Welcome to the 4th lesson! We now move from mapping to Interception. Previously, we have acted like scouts mapping out a territory—finding the server and discovering the specific doors and windows (API endpoints) using tools like ffuf. We now know where the application lives and how to access it. However, knowing that a door exists is different from seeing who is walking through it and what they are carrying.
Today, we will learn how to step into the flow of traffic between a user and the server. This technique allows us to capture data in real-time, modify requests before they reach the server, and uncover sensitive information like passwords or authentication tokens that static scanning might miss. This is often called a Man-in-the-Middle (MITM) scenario, and it is one of the most powerful ways to test an application's logic and security handling.
To intercept traffic, we use a tool called a Proxy. Normally, when you visit a website, your computer connects directly to the server. The server replies directly to you. In this direct connection, the data is invisible to anyone but you and the server (assuming the connection is encrypted).
A proxy sits in the middle of this conversation. Instead of talking to the server, your computer talks to the proxy. The proxy then forwards your message to the server. When the server replies, it talks to the proxy, which then hands the message back to you. Because the proxy holds the message before passing it along, it can "open the envelope," read the contents, and even change the words inside before resealing it.
This is critical for penetration testing because modern web applications often rely on complex data exchanges that are not visible in the URL bar. By using a proxy, we can see the raw JSON data, hidden headers, and cookies the application uses to maintain sessions. It turns the invisible background chatter of the web into something we can read, analyze, and manipulate.
The tool we will use for this is mitmproxy. It is an interactive, SSL-capable man-in-the-middle proxy for HTTP and HTTPS. It is incredibly popular because it allows for deep inspection and scripting using Python. While many tools exist, mitmproxy is favored for its flexibility and terminal-based interface, which is perfect for server environments.
When you launch mitmproxy, it starts a service on your machine (usually on port 8080). You then configure your browser or device to route traffic through that port. Once connected, every request you make appears in the mitmproxy console list.
Here is what the console output might look like when you visit a login page:
You can select any of these requests to view the details. You would see the headers, the body of the request (like the username and password sent during login), and the server's response. In the CodeSignal environment, mitmproxy is pre-installed. While we often use the interactive interface manually, today we will focus on automating this analysis using scripts to capture specific data automatically.
One of the most powerful features of mitmproxy is its Scripting API. While our application is built in TypeScript, mitmproxy uses Python for its automation. Don't worry if you are new to Python; the scripts we will write are concise and follow a logical structure similar to the middleware you've already seen.
Instead of manually watching thousands of requests scroll by, we can write a Python script to filter the noise and alert us only when something interesting happens. The script works by hooking into specific "events" in the traffic flow.
The two most common events we use are request and response. The request event triggers every time the client sends data, allowing us to inspect outgoing data like API calls. The response event triggers when the server replies, allowing us to look for things the server is sending back, such as access tokens.
Let's look at how to set up a basic script. We import the http module from mitmproxy to handle web traffic objects.
intercept_script.py
In the code above, we define a function named request. mitmproxy automatically calls this function whenever it receives a request. We check whether the URL path contains /api/. If it does, we print the HTTP method (like GET or POST) and the body of the request.
To run this script, pass it to mitmproxy using the -s flag:
This launches the interactive mitmproxy console with your script loaded. Every intercepted request will trigger your request function automatically. If you prefer a non-interactive, terminal-only output (which is common in scripted or headless environments), use mitmdump instead:
mitmdump runs the same scripting engine but simply prints all output to the terminal without the interactive UI, making it ideal for automated pipelines and the practice exercises in this course.
With our script running, we can start hunting for vulnerabilities. The primary goal here is to find Broken Authentication or Sensitive Data Exposure. Developers often assume that because data is sent via an API call in the background, users won't see it. Our proxy proves this assumption wrong.
One common weakness is finding Session Tokens or API Keys in places where they shouldn't be, such as in the URL or in an unencrypted HTTP body. If our script flags a request like GET /api/user?token=abc12345, we know we have found a vulnerability. Tokens in URLs are logged by browser history and proxy servers (like ours!), making them easily stolen.
Another flaw is Verbose Error Messages. Sometimes, if you modify a request to send invalid data, the server crashes and sends back a stack trace containing database passwords or internal file paths. By sitting in the middle, we can tweak a request — changing a user ID from 100 to 101, for example — to test for IDOR (Insecure Direct Object Reference), checking whether we can access someone else's data simply by asking for it.
Now that we know how easy it is to intercept traffic, how do we defend against it? The most important defense against interception is Encryption (HTTPS). However, simply having HTTPS isn't enough if the browser can be tricked into using plain HTTP. This is where HSTS (HTTP Strict Transport Security) comes in.
HSTS is a security header that the server sends to the client. It tells the browser, "From now on, only talk to me using a secure HTTPS connection. Never use plain HTTP, even if the user asks for it." This prevents attackers from performing "downgrade attacks" in which they force a user's connection to be unencrypted so they can read it.
Here is how we implement this in a Node.js Express application. We use middleware to add this header to every response.
learn-pastebin/src/server/middleware/security.ts
By setting this header, we ensure that once a user has connected securely, their browser will refuse to connect insecurely for the next year. This makes it much more difficult for a casual attacker on a public Wi-Fi network to intercept the traffic.
While we cannot stop a user from proxying their own traffic (as we do in testing), we can detect whether incoming requests have passed through a proxy. This is useful for identifying whether someone is probing our application or whether a user is trying to bypass IP-based restrictions.
Proxies often leave "fingerprints" in the HTTP headers. Common headers include Via, X-Forwarded-For, or X-Proxy-ID. While legitimate load balancers use these too, seeing them on a direct client connection can be suspicious in certain contexts. We can write middleware to detect these headers.
This code defines a list of known proxy headers. It checks the incoming request (req.headers) to see if any of them are present. If suspicious is true, it logs a warning. This doesn't stop the attack, but it gives the security team visibility into potential reconnaissance activity coming from specific IP addresses.
In this lesson, we explored Traffic Interception. We learned that:
- Proxies like
mitmproxysit between the client and server to capture and modify data. - Interception scripts allow us to automate the discovery of sensitive data, such as tokens and
APIkeys. HSTSprotects users by forcing encrypted connections, preventing downgrade attacks.- Header analysis allows defenders to detect the presence of proxies and potential unauthorized scanning.
You now understand how to look inside the data stream of an application. In the upcoming practice exercises, you will write a TypeScript script to intercept a login token and then implement the defenses to harden the application against these inspection techniques.
