Welcome back! In our previous lesson, we acted as network scouts. We used Nmap to stand outside a server and identify which "doors" (ports) were open and which technology was running behind them. We discovered that our target is running a Node.js Express application on port 3000. Identifying the technology stack is a crucial first step, but knowing that the server exists is not enough to test its security. We need to know exactly which pages, files, and API endpoints are accessible.
This phase is called Application Enumeration. Just because a website has a navigation bar does not mean those are the only pages available. Developers often leave behind hidden administrative panels, configuration files, or backup directories that are not linked anywhere on the homepage. In this lesson, we will move from scanning ports to scanning paths. We will learn how to map the internal structure of an application to find these hidden assets, and then we will learn how to detect and stop this behavior using Rate Limiting.
To find hidden content on a web server, we use a technique called Directory Brute-Forcing or Fuzzing. Since the web server will not voluntarily provide a list of every file it hosts, we must guess. We automate the process of asking the server, "Do you have a file called /admin? Do you have /login? Do you have /backup?" thousands of times per minute.
This might sound crude, but it is incredibly effective. This technique relies on the fact that humans are predictable. Developers tend to use standard naming conventions like config, uploads, api, or v1. If we use a list of common directory names, we have a high probability of finding valid endpoints that the developer thought were "hidden" simply because they did not create a link to them.
There is a subtle distinction between these terms. Brute-forcing generally refers to trying every possible combination of characters (like aaaa, aaab, aaac), whereas Fuzzing in this context usually refers to using a pre-made dictionary of known words to see which ones elicit a response. For web reconnaissance, we almost always use dictionary-based fuzzing because it is much faster and more targeted than pure brute-forcing.
To perform this fuzzing efficiently, we need a tool designed for speed. The industry favorite for this task is ffuf (Fuzz Faster U Fool). It is a command-line utility written in the Go programming language, making it extremely fast at processing web requests. In the CodeSignal environment, ffuf is already installed and ready for you to use.
The core concept behind ffuf is the Wordlist. A wordlist is simply a text file containing thousands of common directory and file names, with one word per line. ffuf reads this list and replaces a keyword (usually FUZZ) in your target URL with words from the list.
Here is the basic syntax for a scan. We tell ffuf two main things: where to look (-u for URL) and what list of words to use (-w for Wordlist). Note that in the URL, we place the word FUZZ where we want the guessing to occur.
When you run this command, ffuf will begin sending requests. Most web servers return a 404 Not Found status code when a file does not exist. ffuf is smart enough to hide these errors and only show you the "hits" — usually responses with a 200 OK, 301 Redirect, or 403 Forbidden status.
Here is what the output typically looks like:
In this example output, ffuf discovered three endpoints: api, public, and users. These are paths we might not have discovered otherwise.
Once ffuf has identified potential endpoints, we must switch to manual verification. Automated tools are great for discovery, but they do not understand context. We need to inspect the actual content of these pages to determine if they are interesting or vulnerable. For this, we use curl (Client URL), a command-line tool for transferring data using URLs.
When we manually probe an endpoint, we are looking for specific details: Does the endpoint return JSON data? Does it reveal sensitive information? Does it require authentication? We use the -i flag with curl to include the HTTP Headers in the output, as they often contain clues about caching, content types, or server versions.
Let's inspect the /api endpoint we discovered in the previous step:
The output might look like this:
This response confirms that /api is a valid endpoint and it returns JSON. The message "Welcome to the Pastebin API v1.0" hints that there might be version-specific vulnerabilities or documentation to investigate. This manual verification step is critical for deciding which discoveries are worth investigating further.
Fuzzing is not limited to directory names alone. We can also use it to find hidden Query Parameters. Sometimes, developers hide features behind specific parameter names, such as ?debug=true, ?admin=1, or ?test_mode=on. These parameters can sometimes bypass security checks or reveal verbose error logs that help an attacker.
To hunt for these, we simply move the FUZZ keyword to the parameter section of the URL. Instead of searching for new files, we keep the file the same (e.g., /api/snippets) and guess the parameter names.
Here is how we might search for hidden parameters on an API endpoint:
In this command, the -fs 45 flag is essential. It stands for Filter Size. When fuzzing parameters, the server will usually return the standard page (size 45 bytes, for example) if the parameter is invalid. We want ffuf to ignore those standard responses and only show us responses that have a different file size, which indicates that our guessed parameter caused the server to do something different.
However, be aware that -fs is a blunt instrument: it filters out every response matching that exact byte size, not just the "default" ones. If a valid, interesting endpoint happens to return a response of the same size as the standard page, ffuf will silently discard it. In practice, this means you should treat -fs results as a starting point rather than a definitive list, and consider spot-checking a few filtered responses manually to make sure nothing important was accidentally hidden.
Now let's switch hats and look at this from the defender's perspective. How do you know if someone is fuzzing your application? Enumeration attacks are "noisy." Unlike a stealthy manual inspection, tools like ffuf generate thousands of requests in a very short time.
If you examine your server logs during an attack, you will see a massive spike in traffic. You will specifically see hundreds of 404 Not Found errors appearing sequentially as the attacker's wordlist guesses incorrect filenames. Additionally, unless the attacker configured their tool specifically, the User-Agent header in the request will often identify the tool being used, such as User-Agent: Fuzz Faster U Fool v1.5.0.
Early detection is vital. If you see this pattern, it means someone is mapping your application right now. They have not necessarily broken in yet, but they are looking for weak points. We need a way to automatically detect this high volume of requests and block them before they can map our entire infrastructure.
The most effective defense against automated enumeration is Rate Limiting. Rate limiting restricts how many requests a user (identified by their IP address) can make within a specific timeframe. If a user exceeds this limit, the server temporarily blocks them and usually returns a 429 Too Many Requests error. This makes fuzzing painfully slow and impractical for the attacker.
In the CodeSignal environment, we have the express-rate-limit library pre-installed for you. We will create a middleware function that enforces these limits.
First, we import the library and configure the rules in a dedicated file.
learn-pastebin/src/server/middleware/rateLimiter.ts
In this configuration, we set windowMs to 1 minute and max to 30. This means a single IP address can only make 30 requests per minute. Since ffuf attempts to make thousands of requests per minute, it will hit this limit almost immediately and fail.
Next, we need to apply this middleware to our application. We create a helper function to apply it to our API routes.
By applying this to /api, any attempt to brute-force our API endpoints will result in the attacker getting blocked after only 30 attempts, effectively neutralizing the speed advantage of their tools.
In this lesson, we explored Application Layer Reconnaissance. We learned that:
- Enumeration is the process of mapping out an application's hidden structure.
- Fuzzing uses wordlists to guess valid directory names and parameters.
ffufis a powerful tool for automating these guesses, whilecurlis used for manual verification.- Rate Limiting is a critical defense that detects high-volume traffic and blocks automated tools.
You have now learned how to find the hidden doors in an application and how to install "security cameras" (rate limiters) to stop others from doing the same. In the upcoming practice exercises, you will use ffuf to discover a hidden administration endpoint and then write the TypeScript code to secure the application against that very same scan.
