If you’ve been following this blog, you know my go-to fuzzing tool has long been FFUF. But if FFUF does a great job fuzzing GET parameters, user passwords or 2FA codes, I have found that Feroxbuster does a better job uncovering hidden API endpoints.
To give a bit of context, what we are looking for are API endpoints that you have not been able to locate by browsing through the app manually, visiting each page and trying out all the features, before exporting a list of API endpoints you found (for a full explanation, check out my post on how to build an OpenAPI 3.0 documentation file). We are also looking for endpoints that are not mentioned in the API documentation that you may have been provided.
In other words, we are looking fo undocumented API endpoints or endpoints not linked from anywhere else in the app, as far as you can see.
Install FeroxBuster
If you’re using Kali Linux, installing Feroxbuster is straightforward:
sudo apt update
sudo apt install feroxbuster
However, know that the Kali repositories don’t always provide the latest version. So once installed , take a second to update the app with:
feroxbuster -U
(you may need to sudo
).
Also know that Feroxbuster has a full documentation available here.
Scan for endpoints using the GET method
For the following demonstration, I am using the c{api}tal vulnerable app as a target, installed locally on my home network (if you want to know more about c{api}tal, I wrote a full walkthrough here).
We can start by scanning the app with the following command:
feroxbuster -u http://192.168.1.26:8000/api/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -H 'Authorization: Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IlNhbW15IiwiZXhwIjoxNjgzNTgwODE2LCJzdWIiOiJhY2Nlc3MifQ.QCYFvWCrs74U_6bs8SYx6hR5QhjKHkKOwdJh9x8tlIo'
Let’s break it down:
-u http://192.168.1.26:8000/api/
this set the URL we want to fuzz (in c{cap}ital, all API endpoints are located in the
/api
path).
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
this sets the wordlist we want to use (here, I have selected a classic web content discovery wordlist from the Seclists collection).
-H 'Authorization: Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IlNhbW15IiwiZXhwIjoxNjgzNTgwODE2LCJzdWIiOiJhY2Nlc3MifQ.QCYFvWCrs74U_6bs8SYx6hR5QhjKHkKOwdJh9x8tlIo'
the -H
flag lets us add request headers to the query – here we are adding a token that c{cap}ital requires and that was assigned to us when logging in as a user.
By default, Feroxbuster sends its requests using the GET method.
What we see here is that some of the endpoints return a 200 status code. This means they are directly accessible with nothing more than the request headers we supplied (the authorization token in our case).
The other endpoints return a 405 status code. This means they are accessible, but not with the GET method (405 means Method Not Allowed).
So let’s see what happens if we scan with another method.
Scan for endpoints using the POST method
Let’s send the same request, adding -m POST
to switch to the POST method:
feroxbuster -u http://192.168.1.26:8000/api/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -H 'Authorization: Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IlNhbW15IiwiZXhwIjoxNjgzNTgwODE2LCJzdWIiOiJhY2Nlc3MifQ.QCYFvWCrs74U_6bs8SYx6hR5QhjKHkKOwdJh9x8tlIo' -m POST
Here, we see that most of the endpoints that were accessible with the GET method now return a 405, meaning they are not accessible using the POST method, which kinda makes sense.
The other endpoints return a 422 code (Unprocessable Content). This means the server understands our requests sent with the POST method but is unable to process the contained instructions. In the present case, this means the API is expecting some JSON content in the request body, such as an email and password to log in a user, for instance. So in a real life scenario, we would have to find out what these keys are maybe by comparing with other known endpoints or through trial and error.
The articles endpoint is interesting. Being familiar with c{api}tal, I can tell you this endpoint can be accessed with the GET method, in which case it will list the articles in the app.
It can also be used with the POST method when we want to create a new article, in which case we will need to include the title, description and article itself as JSON key:value pairs in the request body.
This explains the response codes we got from this endpoint with both our scans.
And speaking of response codes, you may have noticed that as Feroxbuster was receiving a large number of 404 status codes (for all the words in the wordlist for which a corresponding endpoint wasn’t found), it automatically created a new filter to exclude responses with this status code from the display. This is a pretty handy feature that keeps the output clean and compact (you can also disable this feature if you need to).
Scan for endpoints using the PUT and DELETE methods
To get a more thorough understanding of the endpoints we are getting back, we can run Feroxbuster one last time using the PUT and DELETE methods (we can include as many methods as we want in the -m
tag):
feroxbuster -u http://192.168.1.26:8000/api/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -H 'Authorization: Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IlNhbW15IiwiZXhwIjoxNjgzNTgwODE2LCJzdWIiOiJhY2Nlc3MifQ.QCYFvWCrs74U_6bs8SYx6hR5QhjKHkKOwdJh9x8tlIo' -m PUT DELETE
Here, we see the only endpoint accessible with either of these methods is the user endpoint that returns a 422 status code with the PUT method. This endpoint can actually be used with the PUT method to update an existing user’s data.
None of the endpoints listed here are accessible with the DELETE method.
Closing thoughts
So why use Feroxbuster over FFUF? In my opinion, the output is a lot easier to read and having the request method and status code sitting side by side for each endpoint found is a game changer. Now FFUF also does things that Feroxbuster doesn’t, especially when we want to fuzz GET parameters or user credentials, but that’s a story for another post.
Why use Feroxbuster over a dedicated API fuzzing tool like Kiterunner ? Well, Kiterunner on occasions gave me inconsistent results (like generating a different output when fed the identical command several times over). Also Feroxbuster’s output has more clarity. And the tool is a lot faster.
Having said that, don’t exclude running a Kiterunner scan in addition to Feroxbuster as in my experience it sometimes found a couple of extra endpoints.