API Pentest Guide
API Tests
Make a lab for API pentest
Install a kali VM
Update it
Install Burp Suite (its best if you can have a pro version)
Get the latest jython jar and install and specify the path in burp
Install Autorize from the store
Install foxy proxy in firefox
Set up burp certificate
Set up MITMweb certificate
quit burpsuite if open
set foxyproxy on port 8080
get the certificate from mitm.it and install it
Install postman
sudo wget https://dl.pstmn.io/download/latest/linux64 -O postman-linux-x64.tar.gz && sudo tar -xvzf postman-linux-x64.tar.gz -C /opt && sudo ln -s /opt/Postman/Postman /usr/bin/postman
(check for the dl link of the latest version and adapt the previous command)Install mitmproxy2swagger
sudo pip3 install mitmproxy2swagger
Install git if necessary
Install Docker
sudo apt-get install docker.io docker-compose
Install Go
sudo apt install golang-go
Set up the JSON Web Token Toolkit
Install Kiterunner (see more info below)
Install Arjun
sudo git clone https://github.com/s0md3v/Arjun.git
Install Owasp Zap if necessary
sudo apt install zaproxy
update the Add-OnsOnce you have done all this you can deploy a vulnerable api on another vm and connect it with your attacking machine. You will be all ready to practice.
Install crAPI and vAPI
crAPI
It may take a little while
Access it locally
http://127.0.0.1:8025/
orhttp://127.0.0.1:8888/
To stop crAPI
sudo docker-compose stop
vAPI
Note: make sure that your port 80 is free
API Reconnaissance
Partner APIs are intended to be used exclusively by partners of the provider. These might be harder to find if you are not a partner. Partner APIs may be documented, but documentation is often limited to the partner.
Private APIs are intended for use, privately, within an organization. These APIs are often documented less than partner APIS, if at all, and if any documentation exists it is even harder to find.
Things to look for
Obvious URL naming schemes
dir names
Subdomains
Request and Response headers
Use of JSON and XML
Information gathered using third-party resources
Passive reconnaissance
See OSINT chapter for more detailed explaination useful for passive recon in general
Google Dorking
Git Dorking
Specify parameters: "filename:swagger.json" and "extension: .json"
Search GitHub for your target organizationโs name paired with potentially sensitive types of information, such as โapi key,โ "api keys", "apikey", "authorization: Bearer", "access_token", "secret", or โtoken.โ
TruffleHog
sudo docker run -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=target-name
API Directory
Shodan
The Wayback Machine
Allows you to check out historical changes to your target.
Look for retired endpoints that still exist = Zombie APIs
Finding and comparing historical snapshots of API documentation can simplify testing for Improper Assets Management.
Active Reconnaissance
Nmap
We can run the following scan for any http port found
nmap -sV --script=http-enum <target> -p 80,443,8000,8080
OWASP Amass
amass enum -list
see which data sources are available for Amass (paid and free)sudo curl https://raw.githubusercontent.com/OWASP/Amass/master/examples/config.ini >~/.config/amass/config.ini
create a config file to add our API keysRegister for a free Censys account here
Once it is done and that the account is verified login on search here
Go in my account and get your API ID and Secret
Paste them in the config file with
sudo nano ~/.config/amass/config.ini
amass enum -active -d target-name.com |grep api
amass intel -addr [target IP addresses]
collect SSL certificates, search reverse Whois records, and find ASN IDs associated to the targetamass intel -d [target domain] โwhois
reverse whois on domain nameamass enum -passive -d [target domain]
passively enumerate subdomainsamass enum -active -d [target domain]
actively enumerate subdomainsamass enum -active -brute -w /usr/share/wordlists/API_superlist -d [target domain] -dir [directory name]
brute force subdomains with a wordlist
Gobuster
gobuster dir -u target-name.com:8000 -w /home/hapihacker/api/wordlists/common_apis_160
Kiterunner for active recon
See the documentation below.
DevTools
The devtools in firefox has a filter this way we can search for terms like API or v1 etc.
We can use the copy as cURL function to import it in Postman we just need to select Import and click on Raw Text and then paste the cURL request.
Kiterunner
Useful commands:
Basic scan:
kr scan https://<ip>/ -w routes-large.kite
Pass the Bearer token (to avoid getting too many 403):
sudo ./kr scan https://<IP>/ -w routes-small.kite -H 'Authorization: Bearer TOKEN-HERE'
We can specify in the url /api/vX if we have it but kiterunner can also find it for us with the basic scan. Alissa Knight's whitepaper explains this very well: "By default, when depth isnโt specified, Kiterunner will scan a target at 1 level deep, meaning if you specified a target of server.com, Kiterunner would scan server.com/api. At level 2, it would scan server.com/api/R4 and at level 3, it would scan server.com/api/R4/patient."
To send to Burp Suite append the command with:
--proxy=http://127.0.0.1:8080
(this is done with replay not with scan)If you need to hide some specific response code that are not relevant for your context you can use this flag
--fail-status-codes 404
this will blacklist 404 response codes.
Other interesting commands:
kr brute <target> -w ~/api/wordlists/data/automated/nameofwordlist.txt
brute option will allow us to use txt files as wordlistReplay requests:
Endpoint Analysis
Reverse Engineering an API
If an API is not documented or the documentation is unavailable to you, then you will need to build out your own collection of requests.
Manually with Postman
It's better to sign up for a free account.
We can create a new personal workspace
Then we can create a new collection
Now we will use the capture request feature so we will need to have added the postman proxy in foxy proxy previously
Let's click on the button for this
We need to enable the proxy
We can specify something like this and we need to specify an url
Start capture
You can then move to the web browser and browse in your target interact with it and do as many things as you can think of. This will populate the requests in postman.
Once you have browsed enough you can stop the capture
Go back to your request and select the ones that seem to interact with an API.
Add then to a collection
You can organize you collection say you have a path looking like api/folder1/something and one like api/folder2/something you can make a folder named folder1 and one named folder2 and organize your endpoints this way.
Automatic Documentation
mitmweb
set up you proxy on 8080 on your browser with foxyproxy
mitmproxy will open in the browser
Use the target Application
You will see the requests in mitmproxy
When you are done browsing you can save requests you will get a file named "flows"
Transform the file in an Open API 3.0 YAML file
sudo mitmproxy2swagger -i Downloads/flows -o spec.yml -p http://target -f flow
edit spec.yml and remove the "ignore:" to the ednpoints you do not want to ignore (here we want to kepp all the api endpoints)
We can then rerun mitmproxy2swagger with the
--examples
flagsudo mitmproxy2swagger -i ~/Downloads/flows -o spec.yml -p http://target -f flow --examples
We can go to Swagger Editor
And import our spec.yml file
And you have a clean swagger ready to go :)
We can also import our spec.yml file in postman as a new collection.
API Documentation
overview = the first section of API documentation. Generally found at the beginning of the doc, it will provide a high-level introduction to how to connect and use the API. In addition, it could contain information about authentication and rate-limiting.
API Documentation Conventions
General tips with Documentation
Check purposes of the various endpoints
Check out the collection variables
Tips Postman
Make sure that the baseUrl Value matches up with the URL to your target
Update Authorization for the collection. How to add a valid token:
Go to the root of the collection and click on the folder
You will be able to access the tab "Authorization"
In type select the token type you need. In crapi we will use Bearer Token
Login with the request dedicated to the login and you should get a token
This way you can add it to postman
Note: If you want to add variables this is going to be similar you will have to select the tab variables and add it. Do not forget to save :)
RESTler
According to the documentation RESTler is "RESTler, developed at Microsoft, is the worldโs first stateful API fuzzer that automatically generates tests and automatic execution by first reading the OpenAPI specification in order to automatically find vulnerabilities in the API."
Fetch it here
"If you receive a nuget error NU1403 when building, a quick workaround is to clear your cache with this command: $ dotnet nuget locals all--clear"
Quite a pain to install on kali.
wfuzz
This tool will allow to enumerate methods for API which is really convenient. It is preinstalled on kali.
wfuzz -X METHOD -w /path/to/wordlist -u http://URL/FUZZ
where you seeFUZZ
it will replace with words from the wordlist and as forMETHOD
you can use GET POST and any other http verbif you add the option
--hc
you can hide specific codes like 404 for instance--hc 404,405
To pass a header in wfuzz (Say Authorization for instance) you can use
-H "myheader: headervalue"
you can use multiple header this wayCheck out this doc for more infor on this tool
Convert Postman to OpenApi
You can convert them using Postman to OpenApi
sudo apt install npm
Install nmp if you do not have itsudo npm i postman-to-openapi -g
install postman to openapi cli modep2o myfile.postman_collection.json -f myfile.yml
convert your first file
About response codes
Do not neglect 400 codes, they can help you identify actual endpoint. For example 404 is not found but 401 is unauthorized.
However be also aware that:
Sometimes you will get unauthorized on every endpoint meaning that this theory won't work ;)
Sometimes waf will drop your requests or will give you a 200 with an error page
Postman
Setting up baseurl
To give the base url variable a valid value, select the root of the collection
And on the middle panel select variables. Add your host in the current value (for instance https://myhost.com
), select the url and select Set as variable.
It should look like this:
Set the proper authorization, configure postman with burp (if you do not know how check out Hakluke and Farah Hawa article in the resources below), and you should be able to send requests
Bearer Token
If you use a bearer token and do not want to set up authentication, you can just add a current token in the Authozization tab or the collection's root. Important: Do not forget to Save your changes because it wont work if you don't After this you just have to set the other to inherit auth from parent and you should be good to go.
Scanning API
Note that this step should be done AFTER you have discovered an API and used it as it was intended. You will then avoid being blocked by a WAF
The goal here is to guide and focus the testing. Because, as Corey mentions scans are rarely 100% accurate
In the case of API, it will be helpful to find Security Misconfiguration (see details on this vunerability below)
Scan with OWASP ZAP
You can specify the target URL. But as Corey mentions in his course, the result are improved if we use the target's API Specification file. This file is the documentation we generated when we explored the API and used it as intended or the one that your customer might have provided to you when kicking off the pentest.
So go to Import > Import OpenAPI Definition from File and fill up the fields
Now ZAP GUI should be populated with the endpoint.
We just need to right clik on the root folder and launch an active scan
Next after this step is to make an authenticated scan via the manual explore option
Enable the HUD, Lauch browser and browse around as much as you can.
Then launch another active scan by switching the Attack mode to "On"
If the HUD does not show here are a few things you should check:
Check that all is up to date in ZAP
Help > Check for updates
Disable the tracking protection on firefox. See picture below
Scan with Burp (requires pro account)
You can follow the same methodology we did for ZAP, scan unauthenticated and then authenticate browse around and rescan.
You will need to download the extension OpenAPI Parser. Go to Extender >BApp Store scroll to OpenAPIParser or look for it in the search
You might need to edit the yaml or json file to add the actual host (depending on how you got the documentation)
Go to the tab and click
Browse/Load
, select the yaml or json file you needIt will populate the extension tab.
From this you can either select all endpoints and scan them or just select one and scan it by clicking on "Do an active scan".
Special thanks to my friend Lisandre for pointing me to the Extension
API vulnerabilities
API1:2019 Broken Object Level Authorization
See below for how to test
API3:2019 Excessive Data Exposure
If you get a response and:
It includes more information than what was requested
It has sensitive Information that can be leveraged in more complex attacks
For example in Crapi
In our browser this request
will show this
But in Burp it will leak much more info that could be of use for us (see snippet of response).
Here we get usernames emails etc.
API7:2019 - Security Misconfiguration
Security misconfiguration includes missing system patches, unnecessary features enabled, lack of secure transit encryption, weak security headers, verbose error messages, and Cross-Origin Resource Sharing (CORS) policy misconfigurations.
It can be found manually of course, but if you want to speed up the process automatic scans are efficient to detect these.
API9:2019 Improper Assets Management
API Attacks or specific vulnerabilities tests
Classic Authentication Attacks
For API pentest we can try these classic attacks such as password spraying, bruteforcing or password reset bruteforce.
Password Brute-Force Attacks
The request will be sent to an API endpoint
Payload often in JSON
Might require base64 encoding
Tip: generate passwords specific to your target
Use data found from excessive data exposure if previously found to compile a username and password list
Tools: Burp Suite Intruder, WFuzz, etc.
Wordlist: rockyou or you can find plenty of wordlist online such as this repo: SecList
WFuzz on API
-H
Header option--hc, --hl, --hw, --hh
Hide responses with the specified code/lines/words/chars-d
POST body requests = Use post data (ex: "id=FUZZ&catalogue=1") allows you to fuzz content that is sent in the body of a POST requestExample with crAPI
wfuzz -d '{"email":"a@email.com","password":"FUZZ"}' -H 'Content-Type: application/json' -z file,/usr/share/wordlists/rockyou.txt -u http://127.0.0.1:8888/identity/api/auth/login --hc 405
status codes in the 200s and 300s should be good indicators that you have successfully brute-forced credentials
Password spraying
Many security controls could prevent you from successfully brute-forcing an APIโs authentication. A technique called password spraying can evade many of these controls by combining a long list of users with a short list of targeted passwords. The real key to password spraying is to maximize your user list. The more usernames you include, the higher your odds of compromising a user account with a bad password. Build a user list during your reconnaissance efforts or by discovering excessive data exposure vulnerabilities.
Pull email with grep
I am a huge fan of grep
(but not of regex -_-'). And in his course Corey shares a great grep command to use on a json response you got from excessive data exposure and that you saved in a file with postman.
grep -oe "[a-zA-Z0-9._]\+@[a-zA-Z]\+.[a-zA-Z]\+" response.json
You can then use a command like
sort -u
to get rid of duplicate emails
How to proceed with burp intruder
In proxy Positions we add our var in email and password values and we select the "Cluster Bomb" attack type. In the payload we use simple list and load user and passwords list for each payload set. Once done we just need to analyze results. In case of base64 encoding we juste need to use the Payload Processinf rule "Base64-encode"
Credential Stuffing with Intruder
If you have a CSV file with creds (like the one provided for vAPI) the more convenient way to pass it in the intruder is to proceed as follow
Set the positions like this in the position tab and choose pitchfork attack type
Set up payload set 1 as follow, load the csv file and make a payload processing with a match on
,.*
and leave the replace empty. You might not need the encode char options depending on your targetSet up Payload set 2 as follow, load the csv file and make a payload processing with a match on
.*,
and leave the replace empty. You might not need the encode char options depending on your target.Launch the attack and analyze the results (you can play with Status and length for the analysis). In our example we can see the 200 codes that indicates a successful login.
API Token Attacks
Analyze tokens with Burp Sequencer
Issue a login request to your target. In our case crAPI. This way we get a token
Right click in the request and send it to the sequencer
In configuration Define the start and the end of the token
Start live capture
Analyzing the results will allow you to know if the tokens are predictable or not.
Corey referenced this repo of bad tokens if we want to see what the sequencer results look like with bad tokens
JWT Attacks
JWTs consist of three parts, all of which are base64 encoded and separated by periods: the header, payload, and signature. JWT.io is a free web JWT debugger that you can use to check out these tokens. You can spot a JWT because they consist of three periods and begin with "ey". They begin with "ey" because that is what happens when you base64 encode a curly bracket followed by a quote, which is the way that a decoded JWT always begins.
If youโve captured another userโs JWT or maybe discovered a leaked token during reconnaissance, you can try sending it to the provider and pass it off as your own. There is a chance that the leaked token has not yet expired and can be passed off as your own.
For this part in addition to Corey's course I really recommend the following video by Farah Hawa
JWT Tool
With this we can: analyze JWTs, scan for weaknesses, forge tokens, and brute-force signature secrets.
JWT options
-h
to show more verbose help options-t
to specify the target URL-M
to specify the scan modepb
to perform a playbook audit (default tests)at
to perform all tests-rc
to add request cookies-rh
to add request headers-rc
to add request cookies-pd
to add POST data
jwt_tool <token-value>
Will give details on the token. (you migh to run it 2 times because on the first run it needs to generate a config file along other utility files)jwt_tool -t http://target-name.com/ -rh "Authorization: Bearer JWT_Token" -M pb
scan for common vulnerabilities
The None Attack
When a JWT is using "none" as its algorithm.
Easy win
After decoding the token, you should be able to clearly see the header, payload, and signature.
Change username to get more rights
Once youโve edited the payload, use Burp Suiteโs Decoder to encode the payload with base64; then insert it into the JWT. Importantly, since the algorithm is set to "none", any signature that was present can be removed. In other words, you can remove everything following the third period in the JWT. Send the JWT to the provider in a request and check whether youโve gained unauthorized access to the API.
The Algorithm Switch Attack
There is a chance the API provider isnโt checking the JWTs properly. If this is the case, we may be able to trick a provider into accepting a JWT with an altered algorithm. One of the first things you should attempt is sending a JWT without including the signature. This can be done by erasing the signature altogether and leaving the last period in place, like this: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJnYWJ0ZXN0MUB0ZXN0LmNvbSIsInJvbGUiOiJ1c2VyIiwiaWF0IjoxNjczNDUzOTMwLCJleHAiOjE2NzQwNTg3MzB9.
If this isnโt successful, attempt to alter the algorithm header field to "none". Decode the JWT, update the "alg" value to "none", base64-encode the header, and send it to the provider.
To simplify this process, you can also use the jwt_tool to quickly create a token with the algorithm switched to none.
If provider accepts multiple algorithms, we can alter the algorithm. Example provided by Corey: For example, if the provider uses RS256 but doesnโt limit the acceptable algorithm values, we could alter the algorithm to HS256. This is useful, as RS256 is an asymmetric encryption scheme, meaning we need both the providerโs private key and a public key in order to accurately hash the JWT signature. Meanwhile, HS256 is symmetric encryption, so only one key is used for both the signature and verification of the token. If you can discover and obtain the providerโs RS256 public key then switch the algorithm from RS256 to HS256, there is a chance you may be able to leverage the RS256 public key as the HS256 key.
jwt_tool TOKEN -X k -pk public-key.pem
to leverage this attack with jwt_tool (we will get a new token)
JWT Crack Attack
We try to crack the secret used for the JWT signature hash. We will try this on crAPI
crunch 5 5 -o crAPIpw.txt
create a list of all possible character combinations to use against crAPI. It will create a wordlist of 5 charsjwt_tool TOKEN -C -d /wordlist.txt
to perform the attack in the context of crAPI we will run thisjwt_tool eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJnYWJAdGVzdC5jb20iLCJpYXQiOjE2NTg1MDY0NDYsImV4cCI6MTY1ODU5Mjg0Nn0.7mWRyaqQqcXsTXWmFhACIjS6SL7i5iB-NiXgmKpB0kqz739S1qltSRTYZQXt0GqoMpZmL6XwJ53aoHNerzz6qQ -C -d crAPIpw.txt
With the key we can create any token we want
Crunch is a really great tool. See more use cases here
Exploiting API Authorization
Broken Object Level Authorization (BOLA)
Access to resources that do not belong to you
Ingredients for successful exploitation
Resource ID: a resource identifier will be the value used to specify a unique resource. This could be as simple as a number, but will often be more complicated.
Requests that access resources. In order to test if you can access another user's resource, you will need to know the requests that are necessary to obtain resources that your account should not be authorized to access.
Missing or flawed access controls. In order to exploit this weakness, the API provider must not have access controls in place. This may seem obvious, but just because resource IDs are predictable, does not mean there is an authorization vulnerability present.
Finding Resource IDs and Requests
Identify structure and patterns
Ideas of requests and patterns
Image: APISec University - Corey Ball
Questions to ask yourself:
What can you do with this app?
Do you get your own profile?
Can you upload files?
Do you have an account balance?
Is there any part of the app that has data specific to your account?
Testing strategy (A-B Testing)
Create a UserA account.
Use the API and discover requests that involve resource IDs as UserA.
Document requests that include resource IDs and should require authorization.
Create a UserB account.
Obtaining a valid UserB token and attempt to access UserA's resources.
BOLA Example in crAPI
Example of exploitation. In crAPI, we create 2 users and use the token of user B to access the location of the vehicule of user A
Request and reponse for user A (legitimate)
Request and response of user A with user B token (should not be possible)
BOLA Example in vAPI
In vAPI we can access another user info just by specifying the id in the endpoint.
First we need a valid Authorization token. In this endpoint the authorization is going to be
user:password
encoded in base64 so in my case I have a user named test with password test so I need to encodetest:test
in base64, like thisdGVzdDp0ZXN0
This way I can request info on a user with this endpoint/vapi/api1/user/<userId>
. Let's get info on the user that has id 1. We get info that we should not be able to have
Broken Function Level Authorization
Perform unauthorized actions
Ingredients for successful attack
Resource ID: a resource identifier will be the value used to specify a unique resource.
Requests that perform authorized actions. In order to test if you can access another update, delete, or otherwise alter other the resources of other users.
Missing or flawed access controls. In order to exploit this weakness, the API provider must not have access controls in place.
Hunting for functional requests: POST, PUT, DELETE, and potentially GET with parameters.
Important reminder by Corey: Please take note: When successful, BFLA attacks can alter the data of other users. This means that accounts and documents that are important to the organization you are testing could be on the line. DO NOT brute force BFLA attacks, instead, use your secondary account to safely attack your own resources. Deleting other users' resources in a production environment will likely be a violation of most rules of engagement for bug bounty programs and penetration tests
In crAPI, we can illustrate this attack by updating video the name of the video of user a with the token of user B. This is going to be only lateral
Here we make the legitimate request of user A updating their video
Here is the attack of the request with user B token to update the video of user A
To make this attack and elevate our privilege, we can try to delete a video.
When modifying to DELETE we get this message
In the endpoint
/identity/api/v2/user/videos/33
it specifies user what if we change this to admin. It works. We elevated our privilege and where able to make admin actions
Corey mentions that the Authorization vulnerabilities continue to be the most common API vulnerabilities.
Testing for Improper Assets Management
Discovering unsupported and non-production versions of an API.
Examples of path
Examples of headers
Example of query parameter or request body
Non-production versions of an API include any version of the API that was not meant for end-user consumption
Once we have discovered an unsupported version of the API, we will test for additional weaknesses.
How to find
You can discover mass assignment vulnerabilities by finding interesting parameters in API documentation and then adding those parameters to requests. Look for parameters involved in user account properties, critical functions, and administrative actions. Intercepting API requests and responses could also reveal parameters worthy of testing. Additionally, you can guess parameters or fuzz them in API requests that accept user input. I recommend seeking out registration processes that allow you to create and/or edit account variables.
How to test
Test from both unauthenticated and authenticated perspectives.
We can the collection runner (it will test requests across the entire collection) in Postman multiple times along with an environmen variable
{{ver}}
to specify the version we want to look for.To use the var we first need to use the find an Replace function (on bottom of the Postman window), find all the v2 an replace them with
{{ver}}
Then we just need to add the variable in our variables update its value to another version (v1 for example), run the collection runner and analyze the results.
Mass Assignment
An attacker is able to overwrite object properties that they should not be able to.
Ingredients
Requests that acceot user input and alter values available to the user
Missing security controls
How to find Mass Assignment vulnerabilities
Find interesting parameters in API documentation, add them to requests.
Look for parameters involved in user account properties, critical functions, and administrative actions.
Use AOI as intended to study parameters used by API provider
Understand names and spelling conventions
Fuzz parameter values in requests
Check the target's account registration process if present
Example with crAPI
First we create an account with a classic user. And see what a successful response look like (+ we send the request to the repeater)
Now we try to add another user but make it an admin with a parameter
isadmin
(we can look for these types of parameter if we have access to the admin documentation). Our user is register and with admin rights.If we do not have admin doc we could try these
Or we could fuzz by sending the request to the intruder and setting the vars on the parameter we wish to add
Param Miner extension on Burp
Install it from the extender
Then we just need to right click on the request we wish to check and select
Extension > Parama Miner > Guess params > Guess JSON parameter
And then in the window that pops up we select the options we need
We can check the results in
Extender > Extenstions > Param Miner > Output
Other Mass Assignment Vectors
More than trying to become adnin
Gain unauthorized access to other organizations
Example
API functions other than registration can be vulnerable
Example with vAPI
In vAPI the documentation specifies that api6 is dedicated for testing mass assignment
Let's first use
/vapi/api6/user/me
to see the parameters we get. Remember here we need to encode our creds in the format user:pass in base64 and pass them in the Authorization-Token header.We have a credit parameter let's try to add ourselves 800 credits with a post request on this endpoint
/vapi/api6/user
.It seems to work, let's check this with the other endpoint
It works and we even get a flag
Server-Side Request Forgery (SSRF)
An application retrieves remote resources without validating user input
An attacker can supply their own input, in the form of a URL, to control the remote resources that are retrieved by the targeted server. Possible consequences
Gain access to sensitive data
Completely compromise the target host
Growing threats on API
Types of SSRF
In-Band SSRF
For an In-Band SSRF, a URL is specified as an attack. The request is sent and the content of your supplied URL is displayed back to you in a response. Once you have discovered an In-Band SSRF vulnerability you could leverage control over the URL to scan the internal network environment, gather sensitive information from the localhost, or attempt to perform a remote code execution attack.
Example
Intercepted Request
Attack:
Response
Blind SSRF
Blind (or Out of Band) SSRF takes place when a vulnerable server performs a request from user input but does not send a response back to the user indicating a successful attack. The app does not provide an unusual response to the user, but the server does make the request to the URL specified by the attacker. In this case, to know if the request was made you will need to have some control over the web server that is specified in the attack. In this case, the response is returned and we do not have any indication that the server is vulnerable. Instead of
http://localhost/secrets
, we will need to provide the URL to a web server that will let us see if a request is actually made. Burp Suite Pro has a great tool called Burp Suite Collaborator. Collaborator can be leveraged to set up a web server that will provide us with the details of any requests that are made to our random URL. You can also use one of these other free sites:In case of pentest you might want to setup your own web server instead of using public tools. You can also deploy your own private Burp Suite Collaborator server. See how to do this here. In a CTF context a simple
python3 -m http.server 80
usually does the trick too.Example
Intercepted Request
Attack:
Response:
Ingredients for SSRF
Look for requests that have any of the following:
Include full URLs in the POST body or parameters
Include URL paths (or partial URLs) in the POST body or parameters
Headers that include URLs like Referer
Allows for user input that may result in a server retrieving resources
SSRF Example with crAPI
It is worth fuzzing the parameter where you will put the url to request using the intruder to check what is working. We can use PayloadAllTheThings to find Payloads to try out.
In crAPI's case the endpoint
/workshop/api/merchant/contact_mechanic
is worth fuzzing.Here is how I filled the positions tab and I set my variable on the mechanic_api paramter
And here is the payloads tab. Do not forget to uncheck the URL encode option if you want to have valid requests
We can see on collaborator webhook and my webserver that these request worked
See the response from webhook for example
From the results we can see that we can not query localhost but we can query the rest.
SSRF Example with vAPI
In vapi if we can try this endpoint
/vapi/serversurfer
If we send a get request as is we get and interesting response that hints that it takes a url parameter
If we try to add a url parameter in the url it sends a valid request however 127.0.0.1 sends back a 403 response
If we send to an external url such as burp collaborator it works and we get the body of the reponse back but encoded in based64
Injection Attacks
Discover by fuzzing all potentials inputs
Headers
Query string parameters
Parameters in POST/PUT requests
Interesting note by Corey: The more you know about the API, the more you can focus your attacks and increase your chance of finding a vulnerability. This is where your reconnaissance efforts will really pay off. If you know what database the application uses, what operating system is running on the web server, or the programming language in which the app was written, youโll be able to submit targeted payloads aimed at detecting vulnerabilities in those particular technologies.
When reviewing API documentation, if the API is expecting a certain type of input (number, string, boolean value) send:
A very large number
A very large string
A negative number
A string (instead of a number or boolean value)
Random characters
Boolean values
Meta characters
SQL Injection Metacharacters
SQL Metacharacters are characters that SQL treats as functions rather than data. For example,
--
is a metacharacter that tells the SQL interpreter to ignore the following input because it is a comment.
NoSQL Injection
APIs commonly use NoSQL databases due to how well they scale with the architecture designs common among APIs. Also, NoSQL injection techniques arenโt as well-known as their structured counterparts. Due to this one small fact, you might be more likely to find NoSQL injections.
Common NoSQL metacharacters
OS Injection
Command separators to pair multiple commands
Common OS commands
Fuzzing an entire API collection with Postman
The collection runner in postman is really convenient for fuzzing an entire API collection
We can duplicate a collection, select multiple interesting requests, set fuzz variables, proceed with various payloads and analyze the results.
When a request gives interesting results, we can send it to the intruder or WFuzz
If you want to fuzz an interesting request with wfuzz take the request from burp by saving it in a file with "copy to file" option and use the file and
wfuzz --help
to write your wfuzz command
Injection Example with crAPI
We follow the process described by Corey with postman.
We send the interesting request to the intruder, in crAPI it is this endpoint
/community/api/v2/coupon/validate-coupon
. During the analysis with postman we got interesting results with noSQL injection payloadsWe set our positions tab
We set the Payloads type (I used the list given by Corey you can find it above)
To have the best results it was better to uncheck the URL-encode payload
Finally we can attack and analyze the results. We get multiple 200 with valid coupon codes
Here is the command that Corey uses to fuzz this request with WFuzz
wfuzz -z file,usr/share/wordlists/nosqli -H "Authorization: Bearer TOKEN" -H "Content-Type: application/json" -d "{\"coupon_code\":FUZZ} http://crapi.apisec.ai/community/api/v2/coupon/validate-coupon
He then uses--sc 200
to filter out the results. To better analyze results he recommends proxying wfuzz traffic through burpsuite-p localhost:8080
Injection example with vAPI
In the documentation we can see that the request to test for injection is this endpoint in api8
/vapi/api8/user/login
Let's fuzz this specific request with burp
Here is how I set the positions tab
In this case turns out we get better results if we keep the URL-encode chars checked. Our Payloads tab looks like this.
Then we can analyze the results. The request giving 500 response code are interesting because we get useful error messages
We can send one of these request in the repeater and try different payloads. The successful one is
" OR 1=1#
Now we just need to use the other request from api8 to get the secret and use the auth key as as the Authorization token like this.
Evasion and combining techniques
A really interesting chapter in APISec Uni on evasion techniques.
Evasive Maneuvers
String terminators
Null bytes and other combinations of symbols are often interpreted as string terminators used to end a string. If these symbols are not filtered out, they could terminate the API security control filters that may be in place. When you are able to successfully send a null byte it is interpreted by many back-end programming languages as a signifier to stop processing. If the null byte is processed by a back-end program that validates user input, then the security control could be bypassed because it stops processing the following input.
String terminators can be placed in different parts of the request, like the path or POST body, to attempt to bypass any restrictions in place. For example, in the following injection attack to the user profile endpoint, the null bytes entered into the payload could bypass filtering
In this example, input validation measures might be bypassed due to the null byte placed before the SQL injection attempt.
Case Switching
Examples
Original request
Modified requests with case switching
Encoding Payloads
To take your WAF-bypassing attempts to the next level, try encoding payloads. Encoded payloads can often trick WAFs while still being processed by the target application or database. Even if the WAF or an input-validation measure blocks certain characters or strings, they might miss encoded versions of those characters. Alternatively, you could also try double encoding your attacks.
Imagine that the API provider has a control in place that provides one round of decoding to requests that are received.
URL Encoded Payload: %27%20%4f%52%20%31%3d%31%3b
API Provider URL Decoder: ' OR 1=1;
WAF Rules detect a fairly obvious SQL Injection attack and block the payload.
Double URL Encoded Payload: %25%32%37%25%32%30%25%34%66%25%35%32%25%32%30%25%33%31%25%33%64%25%33%31%25%33%62
API Provider URL Decoder: %27%20%4f%52%20%31%3d%31%3b
This could perhaps pass by a bad WAF rule to later be decoded and interpreted.
Payload processing with burp
When we can successfully bypass a waf, we can use the payload processing option in Burp Intruder when fuzzing
Intruder > Payloads > Payload Processing
to add the rule you need.Test by starting an attack and update if necessary
Evasion with WFuzz
See here the advanced secion of the WFuzz docs to find the payload processing options.
wfuzz -e encoders
to see a list of all Wfuzz encoders
To use an encoder, add a comma to the payload and specify its name.
wfuzz -z file,wordlist/api/common.txt,base64 http://url-of-your-target/FUZZ
wfuzz -z list,TEST,base64-md5-none
To have a payload processed multiple encoders specify them with a hyphen
Combining Techniques
Combining multiple techniques together is what will help you find critical vulnerabilities, increase the impact of your bounties, and more closely emulate advanced attackers.
Once you have found a small crack in the security of an API then you may have found a launchpad for the rest of your attack.
Excessive Data Exposure and Improper Assets Management are both API weaknesses that stand out above the others to combine in order to escalate the impact of your attacks.
Directory traversal fuzzing attack along with the file upload to manipulate where the file is stored
Use Broken Function Level Authorization (BFLA) or Mass Assignment weaknesses to search for Improper Assets Management, injection weaknesses, or Broken Object Level Authorization weaknesses.
When you have discovered mass assignment fuzz the parameter for other weaknesses.
If you are able to update to perform a BFLA attack and update another userโs profile information perhaps you could combine this with an XSS attack.
Combine Injection attacks with most other vulnerabilities.
If you find a BOLA vulnerability that provides you with other usersโ bank account information check to see if you are also able to exploit a BFLA vulnerability to transfer funds.
If you are up against API security controls like a WAF or rate-limiting, make sure to apply evasion techniques to your attacks. Encode your attacks and attempt to find ways to bypass these security measures. If you have exhausted your testing efforts, return to fuzzing wide with encoded and obfuscated attacks.
Misc tips
With an API we need to check as many endpoints as possible sometimes an endpoint will be protected but another will not have the same protection.
A great methodology to use is the one made by David Sopas - MindAPI
Do not forget also to try to enumerate id if for instance you have http://api/user/ try to put 1 in the end
When interactig with json in burpsuite repeater if we find an endpoint we have to add the content type like this in the headers
Content-Type: application/json
Do not hesitate to tamper with responses also (not only requests)
Resources
HTB write ups with API
I think we learn a lot when reading examples of exploitations. Here is a list of writeups with API. (more coming soon we just need for the box to get retired :P )
HTB Backend
HTB Backend 2
Tools
Courses, papers or articles
Standards and references
Wordlists
Practice and labs
Last updated