Guides & Tools


https://github.com/shieldfy/API-Security-Checklist

https://owasp.org/www-project-api-security/

https://www.soapui.org/downloads/soapui/

https://www.postman.com/downloads/


Scanning


  • Burp Scanner:

  • Nessus:

  • Nikto:

  • nmap (with URL):

  • SSLScan:

  • Gobuster:


Information Gathering & Access


  • REST vs SOAP? https://www.soapui.org/learn/api/soap-vs-rest-api/ SOAP typically more vulnerable to XXE REST typically more vulnerable to improper access controls

  • Does the API use a web/swagger UI for requests? Can you setup SOAPUI or Postman? Pipe to Burp for analysis. These tools have good guides to help you setup for API testing.

  • Is HTTPS enforced? Crucial for authentication, tokens or any sensitive data.

  • Is the HSTS Header implemented? Prevent SSL strip attack.

  • Any other security headers missing? X-Content-Type-Options: nosniff X-Frame-Options: deny Content-Security-Policy: default-src ‘none’

  • Software versions in response headers?

  • Any outdated script libraries?

  • Third party scripts?

  • Verbose error messages?

  • Check for excess/sensitive info being returned from the API but simply hidden from the user If through an app on a device or web GUI for example, can you see extra unecessary information in responses but not on the page?

  • Burp Intruder to fuzz for possible API endpoints and start mapping the attack surface: https://gist.github.com/yassineaboukir/8e12adefbd505ef704674ad6ad48743d https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/common-api-endpoints-mazen160.txt

  • Is the API private or public? Check whitelisting if private: A private API should not let you interact with it - drop your VPN to confirm access is restricted.

  • Try to use the following symbols as wildcards (also try when authenticated), e.g.: /api/users/* /api/users/% /api/users/_ /api/users/.

  • Old versions available(check with client if found)? /api/v1/login /api/v2/login

    /api/Event2020/user/pp/(ID) /api/Event2021/user/pp/(ID)


Authentication & Session Management


  • Does the API use ‘Basic Auth’ anywhere, for example during token retrieval?

  • Do credentials, Passwords or security tokens get reflected in any responses? Are they sent multiple times? Credentials should be immediately exchanged for an access Token or Authorization: Bearer JWT or similar.

  • Check that API key is being used and not full creds being sent every time. API keys are much longer than username/password combos, and are therefore much difficult to crack

  • Resource IDs should be obfuscated: i.e. Use /me/orders instead of /user/654321/orders

  • Something like the following example might get you access to another user’s photo album: /api/MyPictureList → /api/MyPictureList?user_id=<other_user_id>

  • Check that the access token is included as a ‘Bearer’ token within the Authorisation header in requests, and is not being sent as a cookie

  • Check for access token/key being invalidated on server after some time - In the case of a JWT, the base-64 decoded version contains linux timestamps in the IAT and EXP fields - check the time difference between these to find out how long it’s valid for.

  • Is there allowance for the token that’s generated to expire at more specific times than each 24 hour period?

  • Check for the issue of Refresh tokens - they can be thought of as Remember Me cookies, which are used to get new Access tokens; refresh tokens are longer lived than access tokens and should be subject to stricter storage requirements to prevent their leakage and can be blacklisted by authorisation server.

  • Check that the API’s access token is being sent either within an Authorization header, cookie or part of POST body It should NOT be sent within the URI, as per web apps

  • If the API is accessed by a token find out whether this token is static. And therefore whether is likely to be hardcoded within a client app, or if it dynamic and expires regularly, requiring a new one to be issued.


Input Validation


  • Reflected XSS seen in JSON responses? Typically reported as informational

  • HTTP request method change? Try swapping out GET, POST, PUT, DELETE, PATCH, INVENTED to see if the web server gives you unexpected information.

  • Try to play between the following content-types (requires formatting of request body) to make the web server behave unexpectedly: x-www-form-urlencoded user=test application/xml <user>test</user> application/json {“user”: “test”}

  • If able to send XML data, check for XXE: Change content-type to ‘application/xml’ and throw in

    <userInfo> <firstName>John</firstName> <lastName>Doe</lastName> </userInfo>

    Does the application respond with XML based errors?

    More payloads: https://github.com/payloadbox/xxe-injection-payload-list

  • Farming Protection (aka Rate Limiting/Throttling): Send a regular request to Intruder for a few hundred requests. If API returns ‘429 Too Many Requests’ then it’s protected.

  • Cross-origin resource sharing checks: Alter header and check response for reflection or * wildcard.

  • Cross-site request forgery: Relevant if API has a web GUI or is using cookies

  • HTTP Parmater Pollution /api/account?id=<your account id> → /api/account?id=<your account id>&id=<admin’s account id>


JWT Tests


! JWT integrity is critical - the server should be setting the standards and verifying them, not the client.

  • Test token expiration (exp field) - Check suitable expiration time is set.

  • NONE hashing algorithm - test via Burp json-web-tokens extension

  • Token Sidejacking - check for user context inside the token

  • Token explicit revocation by the user - Check if the token is invalidated on logout.

  • Token information disclosure - Check for any sensitive user information disclosed inside the token.

  • Token storage on client side - Check browser storage to see how token is stored.

  • Token weak secret - Brute-force JWT private keys (when signed with HS256 (HMAC) hashing algorithm)

  • Key confusion - attempt to change algorithm from RS256 to HS256 using Burp JOSEPH extension

    • RSA key pair might be the same as the TLS web server. Use this to retrieve: openssl s_client -connect target.com:443 | openssl x509 -pubkey -noout
  • Check that tokens are signed on the server-side and not client-side code (i.e. where the token originates)

    • If client side this suggests a hard-coded key
  • Check decrypted JWT for ‘jku’ header - If found browse to URL for public key that verifies the token

  • Check for the ‘kid’ header. If found try looking for the key name/id in the webroot (domain/kid)


OAuth Tests


! Confirm scope with client for these tests.

  • Check SSL/TLS is in place for all OAuth requests output: BR number

  • Check whether service provider’s Authorisation server is checking value of “redirect_uri” parameter before redirecting output: BR number

  • Check lifetime of Temporary Authorisation Code

  • Check for CSRF linking of client app and service-provider accounts output: BR number / repeater request

  • Check whether Temporary Authorisation Token can be replayed to authorisation server to gain new access token output: BR number

  • Check expiry of Refresh Token and Access Token

  • Check whether the authorisation server is vulnerable to a Grant-Type “Downgrade” attack (change response_type parameter to token)

  • Check that the state parameter is set on the request to authorisation server (random string for validation)

  • Check for the existence of handle-based tokens (random strings) over self-contained tokens (JWTs) - handle-based is prefered

  • Check storage method for any tokens that are issued (cookies vs local storage vs browser memory)

  • Check for the existence of rate-limiting on the token/exchange endpoint

  • Check that the client_ID is bound to the authorisation code (attempt to change client ID in the request to the authorisation server)

  • Check for the existence of a code_verifier (for authorisation server to validate integrity of authorisation code)


Endpoint Assessment


Authenticated Response:
Unauthenticated response:
Enumeration:
Accepted methods:
Fuzzing (size limit, illegal characters, data types):
Errors:
Content-type conversion (application/xml, application/javascript, text/html):
Reflected headers:
Encryption:
Security headers:
CORS (Origin header):
Sensitive Info via URL: