Uncovering API Vulnerabilities: Advanced FFUF Fuzzing with POST Requests and Multiple Wordlists
Effective API vulnerability assessment demands a targeted approach, particularly when dealing with POST requests and complex data structures. Generic fuzzing often falls short; instead, a methodical strategy combining FFUF, multiple wordlists, and precise payload manipulation is crucial for identifying authentication bypasses, injection flaws, and unexpected API behaviors.
Setting the Stage: FFUF for POST Requests
POST requests are a prime target for API fuzzing due to their typically rich data payloads, often containing user input in JSON, XML, or URL-encoded forms. Unlike GET requests, where parameters are in the URL, POST data resides in the request body, necessitating specific FFUF syntax to target these fields effectively. FFUF, or Fuzz Faster U Fool, is an incredibly versatile and fast web fuzzer that excels in this domain.
The fundamental command for a POST request in FFUF involves specifying the method with -X POST and the data payload with -d. The FUZZ keyword denotes the injection point. For example, a simple POST request to fuzz a single parameter might look like this:
ffuf -u http://target.com/api/login -X POST -d "username=FUZZ&password=test" -w /path/to/usernames.txt
However, real-world APIs are rarely that simple. They often expect JSON or XML, and you'll want to fuzz multiple parts of the request simultaneously.
Advanced Fuzzing: Multiple Wordlists and Payload Iteration
The true power of FFUF for API fuzzing emerges when you combine multiple wordlists and precisely control their application within complex payloads. This allows for credential stuffing attempts, testing various parameter values, or even fuzzing parameter names themselves.
Defining Multiple Fuzzing Positions
FFUF allows the definition of multiple fuzzing positions using the -w flag multiple times, each associated with a unique keyword (e.g., WORD, PASS, PARAM). This is critical when you need to substitute values from different wordlists into different parts of your POST body.
Consider a JSON login endpoint that expects both a username and a password. We want to test common usernames with common passwords. We can define two wordlists:
-w /path/to/usernames.txt:USER-w /path/to/passwords.txt:PASS
These custom keywords (USER and PASS) are then used in the -d (data) parameter.
Crafting Complex Payloads
When dealing with JSON or XML, the payload string passed to -d must be correctly formatted, including proper escaping if necessary. FFUF will substitute the fuzzing keywords before sending the request. For JSON, you'll often construct a string like:
-d '{"username":"USER", "password":"PASS"}'
Note the single quotes to encapsulate the JSON string, allowing double quotes within for JSON keys and values. When conducting such targeted attacks, especially across various target environments, routing traffic through a reliable proxy like GProxy can be beneficial for managing source IPs or ensuring anonymity during reconnaissance and fuzzing phases.
Practical Example: Fuzzing an Authentication API
Let's simulate fuzzing a hypothetical login API endpoint http://api.example.com/auth/login that expects a JSON payload with username and password fields. We'll use two common wordlists: one for usernames and one for passwords.
Step 1: Prepare Wordlists
Ensure you have appropriate wordlists. For demonstration, let's assume users.txt contains:
admin
test
user
guest
And passwords.txt contains:
password
123456
admin
qwerty
Step 2: Construct the FFUF Command
We'll combine the wordlists and the JSON payload. We'll also filter responses to identify potential successful logins or interesting error messages. A common technique is to hide responses with a standard login failure size (-fs) or status code (-fc).
ffuf -u http://api.example.com/auth/login \
-X POST \
-H "Content-Type: application/json" \
-w users.txt:USER \
-w passwords.txt:PASS \
-d '{"username":"USER", "password":"PASS"}' \
-fc 400,401,403 \
-fs 123,456 \
-v
Let's break down this command:
-u http://api.example.com/auth/login: The target URL.-X POST: Specifies the HTTP POST method.-H "Content-Type: application/json": Sets the necessary header for JSON payloads.-w users.txt:USER: Maps theusers.txtwordlist to the keywordUSER.-w passwords.txt:PASS: Maps thepasswords.txtwordlist to the keywordPASS.-d '{"username":"USER", "password":"PASS"}': The JSON data payload. FFUF will iterate through all combinations ofUSERfromusers.txtandPASSfrompasswords.txt.-fc 400,401,403: Hides results with HTTP status codes 400 (Bad Request), 401 (Unauthorized), and 403 (Forbidden), which are common for failed login attempts.-fs 123,456: Hides results with specific response sizes (in bytes). This is crucial for filtering out consistent error messages. You'd typically run an initial single-request test to determine the size of a "failed login" response.-v: Verbose output, showing more details.
Interpreting FFUF Output
FFUF's output is highly customizable and provides clear indications of discovered resources or behaviors. When fuzzing, pay close attention to:
- **Status Codes:** Look for deviations from expected error codes (e.g., a
200 OKwhere a401 Unauthorizedis expected, or a302 Redirect). - **Content Length:** Significant differences in content length often indicate a different server response, potentially a successful login, a detailed error message, or an unexpected redirection.
- **Response Time:** Anomalies in response time could point to different code paths being executed, potentially due to a valid input or an injection vulnerability.
- **Words/Lines/Chars:** These metrics help differentiate between responses that might have the same status code but different content.
A sample output might look like this:
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ _ /\ \__/
\ \ ,__\\ \ ,__\/\ \ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_/ |\ \ \_/
\ \_\ \ \_\ \ `\___/ \ \_\
\/_/ \/_/ `/ __/ \/_/
v2.0.0-dev
________________________________________________ :: FFUF :: ________________________________________________
Target Url: http://api.example.com/auth/login
Method: POST
Wordlists: users.txt (USER), passwords.txt (PASS)
..[SNIP]..
Status: 200 | Size: 78 | Words: 12 | Lines: 3 | Duration: 123ms | Matched: {"success":true,"token":"..."}, Input: USER=admin,PASS=password
Status: 401 | Size: 54 | Words: 8 | Lines: 2 | Duration: 87ms | Matched: {"error":"Invalid credentials"}, Input: USER=test,PASS=123456
Status: 401 | Size: 54 | Words: 8 | Lines: 2 | Duration: 89ms | Matched: {"error":"Invalid credentials"}, Input: USER=admin,PASS=qwerty
The line with Status: 200 | Size: 78 | ... Input: USER=admin,PASS=password immediately stands out, indicating a successful login with those credentials. This discovery would warrant further investigation, such as attempting to access protected resources with the obtained token or exploring other API endpoints. Tools like Secably can then be employed for automated vulnerability scanning to conduct deeper, more comprehensive analyses of the entire API surface based on these initial findings.
Beyond authentication, this multi-wordlist approach extends to testing various input fields for SQL injection, cross-site scripting (XSS), or command injection. By carefully crafting payloads and using appropriate fuzzing keywords, a pentester can methodically probe API endpoints for a wide array of vulnerabilities. This iterative process, leveraging FFUF's flexibility, transforms what could be a tedious manual task into an efficient, automated discovery phase.