What is Authentication? #
Authentication is the process of verifying the identity of the person making the http request. It ensures that the user is who they claim to be.
What is Authentication bypass? #
Authentication bypass occurs when the attacker bypass the checks that verify the identity of the user by exploiting some vulnerabilities in the web application leading to unauthorized access to data and functionalities.
REST APIs Authentication Methods #
Various methods are used for authentication in REST APIs:
- HTTP Basic Authentication: This method involves sending credentials (username and password) in the request header with each API call. While simple to implement, it’s not very secure as credentials are sent in plaintext.
- HTTP Digest Authentication: Similar to Basic Authentication, but it hashes the password before sending it over the network, making it more secure. However, it’s still susceptible to replay attacks.
- Token-Based Authentication: Clients obtain a token (e.g., JSON Web Token - JWT) after successfully authenticating. This token is then included in subsequent requests headers for authentication. Tokens can have expiration times and can be revoked, enhancing security.
- OAuth: OAuth is a protocol allowing delegated authorization, often used for third-party authentication. Clients obtain an access token from the authorization server, which is then sent with requests to access protected resources.
- OpenID Connect (OIDC): OIDC is an authentication layer built on top of OAuth 2.0, providing additional features like identity verification and token validation. It’s commonly used for single sign-on (SSO) scenarios.
- API Keys: Each client is issued a unique API key, which is included in the request headers for authentication. This method is straightforward but lacks the ability to tie requests to specific users.
- Custom Authentication: Some APIs implement custom authentication mechanisms, such as HMAC (Hash-based Message Authentication Code), where requests are signed with a secret key.
We will explore some case scenarios of the possible vulnerabilities that could arise now.
How to test vulnerabilities in API Authentication? #
Let’s understand some of the common authentication methods and how they can be exploited.
Case 1: HTTP Basic Authentication #
In HTTP Basic Authentication is stateless and credentials (username and password) are sent with every request. This means that each time a user interacts with the system or application, their login information is transmitted. However, because this information is sent in plaintext and isn’t changed between requests, it becomes vulnerable to interception by attackers.
GET /example HTTP/1.1
Host: www.example.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
A replay attack occurs when an attacker intercepts the transmitted credentials and reuses them to impersonate the authenticated user. Since there’s no mechanism in place to prevent the reuse of credentials, the attacker can repeatedly send the intercepted login information to the system, gaining access to resources or performing actions on behalf of the legitimate user without their consent.
It’s a little tedious to perform a replay attack in this case because you need to base64 encode the string every time you send a request.
Solution 1: You can create a bash script that takes a wordlist of passwords, base64 encodes each one, and sends it to ffuf.
Solution 2: Take a password wordlist, use a bash script to encode them, and import them into a new file.
Add the wordlist in Burp Suite, then run Intruder by selecting the base64 string placeholder.
ffuf -r -H "Authorization: Basic BASE64_ENCODED_CREDENTIALS" -X POST -d "parameter=value" -u https://www.example.com
Reference Reports: #
https://hackerone.com/reports/1879549
https://hackerone.com/reports/198673
Case 2: HTTP Digest Authentication #
Unlike Basic authentication, HTTP Digest authentication doesn’t involve sending the username and password in plaintext over the network. Additionally, it offers protection against replay attacks by employing a unique number provided by the server for each authentication attempt.
When a client requests access, the server issues a unique number (nonce) which the client combines with the username, realm, password, and URI. The client then uses an MD5 hashing method to create a hash key from these elements.
GET /protected/resource HTTP/1.1
Host: www.example.com
Authorization: Digest username="Alice",
realm="Example",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/protected/resource",
response="6629fae49393a05397450978507c4ef1",
algorithm=MD5,
qop=auth,
nc=00000001,
cnonce="0a4f113b",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
This hash key, along with the username and realm, is sent to the server for authentication.
On the server side, a similar process occurs to generate a hash key. However, instead of using the password entered by the user, the server retrieves the expected password from its database. It compares the hashed password generated by the server with the hash sent by the client. If they match, access is granted; otherwise, the server can respond with a 401 Unauthorized (indicating no login or failed login) or a 403 Forbidden (denying access).
An HTTP Digest authentication request comprises several components:
- The client uses an HTTP method (e.g., GET, POST, PUT, DELETE).
- It specifies the Uniform Resource Identifier (URI) of the requested resource.
- The client provides a username.
- The server specifies the authentication realm.
- A unique nonce is generated by the server to prevent replay attacks.
- The client increments a nonce count (nc) for each request to thwart replay attacks.
- It generates a unique client nonce (cnonce) for each request to prevent replay attacks.
- The quality of protection (qop) is agreed upon between the client and server, specifying the hash algorithm.
- The client calculates a response hash using provided parameters and the user’s password.
- It selects the algorithm for hash generation, typically MD5 or SHA-1.
- An optional opaque value is provided by the server, which the client must return unchanged.
- The authentication method used is “Digest”.
Vulnerabilities in Digest Authentication: #
-
Man-in-the-Middle (MITM) Attacks: Attackers can intercept hash values and modify Digest Authentication messages to steal credentials or impersonate users.
-
Dictionary Attacks: Since Attackers can attempt to crack passwords using offline dictionary or brute force attacks. Weak or commonly used passwords are particularly vulnerable.
-
Nonce Prediction: In some implementations, predictable or poorly generated nonces may weaken the security of Digest Authentication. Attackers can predict nonce values and use them to mount replay attacks or brute force password cracking.
Case 3: JWT Based Authentication #
Instead of relying on traditional methods like cookies or sessions, JSON-based authentication utilizes JSON Web Tokens (JWTs) to authenticate users.
//Request
POST /api/login HTTP/1.1
Host: www.example.com
Content-Type: application/json
{
"username": "example_user",
"password": "example_password"
}
//Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjM0NTY3ODkwLCJ1c2VybmFtZSI6ImV4YW1wbGVfdXNlciIsImlhdCI6MTUxNjIzOTAyMn0.-bVJBRMz0ckwEeYaAz8A9F9D_lDZ6D3jmngXijv96kE"
}
Here’s how JSON-based authentication typically works:
- Authentication:
- The server validates the username and password when a user logs in.
- If the credentials are correct, the server generates a JSON Web Token (JWT) containing user information (such as user ID, username, or role) and signs it with a secret key.
- The server then sends this JWT back to the client as part of the authentication response.
- Token Storage:
- The client typically stores the JWT in local storage, session storage, or cookies for future requests.
- Storing the token locally allows the client to include it in subsequent requests to authenticate the user without needing to resend their credentials.
- Authorization:
- For each subsequent request to protected resources (such as accessing restricted API endpoints), the client includes the JWT in the request headers.
- The server verifies the JWT’s signature using the secret key to ensure its authenticity and extracts the user information from the token.
- If the token is valid and not expired, the server grants access to the requested resource. Otherwise, it denies access.
- Token Expiration and Renewal:
- JWTs can have an expiration time (expiry), after which they are considered invalid.
- If a token expires, the client needs to request a new token by logging in again or using a refresh token mechanism.
While widely used, JWT-based authentication is susceptible to vulnerabilities. Common issues include:
- Weak Key Generation: Attackers exploit weak or predictable secret keys to forge or tamper with tokens cryptographically.
- Token Expiration: Attackers exploit long token expiration times or inadequate validation, enabling prolonged exploitation of stolen or intercepted tokens.
- JWT Tampering: Attackers modify token payloads, altering user roles or permissions without proper integrity protection, allowing unauthorized access.
- Insufficient Validation: Accepting forged or tampered tokens results from failure to validate JWT signatures, issuer (iss), or audience (aud) claims.
- JWT Invalidation: Absence of mechanisms to invalidate compromised tokens allows attackers to persist with stolen JWTs even after detection.
- Algorithm Vulnerabilities: Insecure algorithms or outdated cryptographic standards expose JWTs to attacks, compromising token integrity and confidentiality.
JWT Authentication has multiple vulnerabilities if not implemented correctly. Check out some videos on exploitation of JWT here.
Reference Reports: #
HackerOne Jira integration plugin Leaked JWT to unauthorized jira users
Authentication Bypass when using JWT w/ public keys
Case 4: API Keys #
API keys work by generating a unique key for each client or application that needs to access the API. The API provider then includes this key in requests made by the client or application. When the API receives a request, it validates the included API key to verify the requester’s identity and permissions. If the key is valid and authorized to access the requested resource, the API processes the request; otherwise, it denies access.
GET /api/resource HTTP/1.1
Host: www.example.com
Authorization: API-Key your_api_key_here
In this case, you can test for: #
-
Insufficient Rate Limiting: APIs lacking proper rate limits on API key usage are susceptible to abuse, such as DoS attacks or excessive data scraping.
-
Test Below Rate Limit: Send requests using a single API key below the rate limit threshold to ensure normal functionality.
-
Test At Rate Limit: Gradually increase request volume until reaching or slightly exceeding the rate limit. Monitor for rate limit-related errors.
-
API Key Exposure: If someone exposes an API key, whether intentionally (e.g., hardcoding it in client-side code) or unintentionally (e.g., through leaks in source code repositories or logs), attackers can misuse it to gain unauthorized access to API resources.
-
IP Whitelisting Bypass: Attackers compromise whitelisted IP addresses to bypass API key authentication and gain unauthorized access to resources.
-
Test Access with Whitelisted IP: Send requests to the API using a whitelisted IP address to verify that access is granted as expected.
-
Attempt Access from Non-Whitelisted IP: Send requests to the API from an IP address not on the whitelist.
Here are some IP addresses you might try to bypass IP whitelisting:
- Localhost IP:
127.0.0.1
- Private IP Ranges:
192.168.x.x
10.x.x.x
172.16.x.x
to172.31.x.x
- API Gateway IPs
- Cloud Service IPs (e.g., AWS, Google Cloud, Azure)
- Common Proxy IPs
- ISP-assigned IPs
Reference Reports #
Google API key leaked to Public
JumpCloud API Key leaked via Open Github Repository.
Bypass rate limit via X-Forwarded-For Header
Case 5: OAuth #
OAuth (Open Authorization) is a widely used protocol for secure API authentication and authorization. Here’s how OAuth typically works in API authentication:
-
Authorization Request:
-
The client redirects the user to the OAuth authorization server’s authorization endpoint.
-
Example HTTP request:
GET /oauth2/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=SCOPE HTTP/1.1 Host: oauth.example.com
-
-
User Authentication and Authorization:
-
The user logs in and approves the requested permissions (scopes).
-
The authorization server redirects the user back to the client application with an authorization code.
-
Example HTTP response:
HTTP/1.1 302 Found Location: <https://client.example.com/callback?code=AUTHORIZATION_CODE>
-
-
Token Request:
-
The client exchanges the authorization code for an access token by sending a token request to the token endpoint of the authorization server.
-
Example HTTP request:
POST /oauth2/token HTTP/1.1 Host: oauth.example.com Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
-
-
Access Token Response:
-
The authorization server validates the authorization code and client credentials and issues an access token.
-
Example HTTP response:
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "ACCESS_TOKEN", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "REFRESH_TOKEN"
-
-
Accessing Protected Resources:
-
The client includes the access token in subsequent API requests to access protected resources.
-
Example HTTP request with the access token in the Authorization header:
GET /api/resource HTTP/1.1 Host: api.example.com Authorization: Bearer ACCESS_TOKEN
-
OAuth, while widely used for secure authentication and authorization, is susceptible to various vulnerabilities. Here are some common issues:
- Authorization Code Interception: Attackers intercept authorization codes exchanged between clients and OAuth servers, gaining unauthorized access to user data.
- Access Token Leakage: Access tokens may be leaked through insecure transmission or storage, allowing attackers to impersonate users and access protected resources.
- Insufficient Token Validation: Failure to properly validate access tokens, including expiration and scope checks, may result in unauthorized access to sensitive data.
- Client Misconfiguration: Poorly configured clients may expose sensitive information or grant excessive permissions, increasing the attack surface and risk of exploitation.
- Token Expiration and Revocation: Inadequate token expiration and revocation mechanisms may leave expired or compromised tokens valid, enabling continued unauthorized access.
- Insecure Token Storage: Storing tokens insecurely, such as in client-side storage or unprotected databases, increases the risk of token theft and misuse.
- Cross-Site Request Forgery (CSRF): CSRF attacks exploit the trust between clients and OAuth servers, allowing attackers to execute unauthorized actions on behalf of authenticated users.
- Insecure Redirects: Improper handling of redirection URLs may lead to open redirect vulnerabilities, enabling attackers to redirect users to malicious websites.
- Insecure OAuth Flows: Poorly implemented OAuth flows, such as the Implicit Flow, may expose access tokens in URLs or browser history, facilitating token theft.
If you want to learn about OAuth vulnerabilities, check out the Portswigger labs.
Reference Reports #
Stealing Users OAuth authorization code via redirect_uri
Stealing Users OAuth Tokens through redirect_uri parameter
Final Thought #
In conclusion, understanding and testing various authentication methods in REST APIs is crucial for maintaining a secure application. Now that you’re familiar with the authentication types encountered in REST APIs, you can leverage the power of Google to delve deeper into each.
Thank you for reading.