API Testing Checklist
MindAPI - API Testing Mindmap
Passive Reconnaissance
Active Reconnaissance
Testing Directories:
gobuster dir -u http://10.x.x.x -w /location/to/wordlist.txtCheck for API calls in Devtools > network Tab or Web App ProxyImport curl request to Postman
Endpoint Analysis
Search for API documentation, if not provided, tsee if it can be discovered
Example API doc Wordlist here
Proxy all traffic to Postman/Burp and capture requests for history
Perform the actions that can be performed within application; this can be filtered in Postman
OR
Import api doc files as new collections
API Documentation Conventions
: or {}
/user/:id
/user/{id}
/user/1337
/account/:username
/account/{username}
/account/mart1an
The colon or curly brackets are used by some APIs to indicate a path variable. In other words, “:id” represents the variable for an ID number and “{username}” represents the account username you are trying to access.
[]
/api/v1/user?find=[name]
Square brackets indicate that the input is optional.
||
“blue” || “green” || “red”
Double bars represent different possible values that can be used.
< >
<find-function>
Angle Brackets represent a DomString, which is a 16-bit string
Set parameters to variable in Postman
Testing
To change versions:
api/v3/login→api/v1/loginCheck other AuthN endpoints:
/api/mobile/login→/api/v3/login/api/magic_linkVerb Tampering:
GET /api/trips/1→POST /api/trips/1POST /api/tripsDELETE /api/trips/1Try Object IDs in HTTP headers and bodies, URLs tend to be less vulnerable.
Try Numeric IDs when facing a GUID/UUID:
GET /api/users/6b95d962-df38→GET /api/users/1Wrap ID with an array:
{"id":111}→{"id":[111]}Wrap ID with a JSON object:
{"id":111}→{"id":{"id":111}}HTTP Parameter Pollution:
/api/profile?user_id=legit&user_id=victim/api/profile?user_id=victim&user_id=legitJSON Parameter Pollution:
{"user_id":legit,"user_id":victim}{"user_id":victim,"user_id":legit}Wildcard instead of ID:
/api/users/1→/api/users/*/api/users/%/api/users/_/api/users/.Ruby application HTTP parameter containing a URL → Pipe as the first character and then a shell command.
Developer APIs differs with mobile and web APIs. Test them separately.
Change Content-Type to
application/xmland see if the API parse it.Non-Production environments tend to be less secure (staging/qa/etc.) Leverage this fact to bypass AuthZ, AuthN, rate limiting & input validation.
Export Injection if you see
Convert to PDFfeature.Expand your attack surface and test old versions of APKs IPAs.
Additional checks:
Mass Assignment Vulnerabilities\
Mass Assignment with account registration for PrivEsc:
Admin Registration
POST /api/admin/create/user
Token: AdminAuthToken
-Redacted-
{
"username": "admin2",
"pass": "Iforgetit0ften",
"admin": true
}POST /create/user
Token: StandardUserAuthToken
-Redacted-
{
"username": "tester",
"pass": "Test1234",
"admin": true
}Blind Mass Assignment: If you suspect an API is vulnerable to Mass Assignment, there is a chance it may ignore the irrelevant variables and accept the variable that matches the expected name and format.
{
"username":"testern",
"email":"[email protected]",
"admin": true,
"admin":1,
"isadmin": true,
"role":"admin",
"role":"administrator",
"user_priv": "admin",
"password":"Password1!"
}Check different Content-Types
x-www-form-urlencoded --> user=test
application/json --> {"user": "test"}
application/xml --> <user>test</user>**If it's regular POST data try sending arrays, dictionaries
username[]=John
username[$neq]=lalala**If JSON is supported try to send unexpected data types
{"username": "John"}
{"username": true}
{"username": null}
{"username": 1}
{"username": [true]}
{"username": ["John", true]}
{"username": {"$neq": "lalala"}}**If XML is supported, check for XXE
Last updated