Session Fixation with Bearer Tokens
How Session Fixation Manifests in Bearer Tokens
Session fixation attacks exploit the fact that authentication systems sometimes fail to properly invalidate and regenerate session identifiers after authentication. In the context of Bearer Tokens, this vulnerability manifests when a system accepts a pre-existing token and binds it to a user's authenticated session without proper validation or rotation.
The classic Bearer Token session fixation scenario occurs when an attacker provides a valid but unauthenticated token to a victim. When the victim logs in, the server binds the existing token to the victim's authenticated session rather than issuing a new token. This allows the attacker to use the same token to access the victim's account.
Consider this vulnerable implementation:
// VULNERABLE: Session fixation possible
app.post('/login', (req, res) => {
const { username, password, token } = req.body;
// Authenticate user
const user = authenticate(username, password);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Problem: Using provided token without validation
const sessionToken = token || generateToken(user);
res.json({
token: sessionToken,
user: { id: user.id, email: user.email }
});
});An attacker can exploit this by first generating a valid token, then tricking a victim into authenticating with that token. The server binds the attacker's token to the victim's session, giving the attacker persistent access.
Another manifestation occurs in token refresh mechanisms. If a refresh token is not properly invalidated after use, an attacker who obtains a valid refresh token can repeatedly obtain new access tokens:
// VULNERABLE: Refresh token fixation
app.post('/refresh', (req, res) => {
const { refreshToken } = req.body;
// Problem: No validation that this refresh token belongs to requester
const newTokens = generateNewTokenPair();
res.json(newTokens);
});Bearer Token systems are particularly vulnerable to fixation when they implement "remember me" functionality that issues long-lived tokens without proper binding to the user's session context or device fingerprint.
Bearer Tokens-Specific Detection
Detecting session fixation in Bearer Token systems requires examining both the authentication flow and token lifecycle management. middleBrick's black-box scanning approach tests for this vulnerability by attempting to fixate tokens during the authentication process.
middleBrick scans for session fixation by:
- Generating a unique token before authentication
- Attempting to authenticate while providing the pre-generated token
- Verifying if the server binds the provided token to the authenticated session
- Testing refresh token mechanisms for similar fixation vulnerabilities
The scanner examines HTTP response headers, token generation patterns, and authentication endpoints to identify fixation risks. Key indicators include:
| Indicator | What to Look For | Risk Level |
|---|---|---|
| Token acceptance without validation | Server accepts arbitrary tokens during login | Critical |
| Static refresh tokens | Refresh tokens remain valid across multiple uses | High | Long-lived tokens without rotation | Tokens valid for months/years without rotation | High |
| Missing token invalidation | No mechanism to invalidate tokens on logout | Medium |
Manual detection techniques include:
# Test token fixation
TOKEN=$(uuidgen)
echo "Generated token: $TOKEN"
# Step 1: Attempt authentication with pre-generated token
curl -X POST https://api.example.com/login \
-H "Content-Type: application/json" \
-d '{"username":"user","password":"pass","token":"'$TOKEN'"}'
# Step 2: Use the returned token
curl -X GET https://api.example.com/protected \
-H "Authorization: Bearer $TOKEN"
# Step 3: Verify if the token is bound to the authenticated usermiddleBrick's scoring system evaluates fixation risk across multiple dimensions, providing severity ratings and remediation guidance specific to Bearer Token implementations.
Bearer Tokens-Specific Remediation
Remediating session fixation in Bearer Token systems requires implementing proper token lifecycle management and validation. The core principle is to never accept pre-existing tokens during authentication and to always issue fresh tokens upon successful login.
Secure implementation pattern:
// SECURE: Proper token handling
app.post('/login', (req, res) => {
const { username, password } = req.body;
// Authenticate user
const user = authenticate(username, password);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Always generate new tokens, never accept provided ones
const tokens = generateNewTokenPair(user);
res.json({
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
expiresIn: tokens.expiresIn
});
});Refresh token security requires binding tokens to specific clients and implementing proper rotation:
// SECURE: Refresh token with rotation
app.post('/refresh', (req, res) => {
const { refreshToken } = req.body;
// Validate refresh token belongs to requester
const tokenData = validateRefreshToken(refreshToken);
if (!tokenData || tokenData.revoked) {
return res.status(401).json({ error: 'Invalid refresh token' });
}
// Revoke the used refresh token
revokeRefreshToken(refreshToken);
// Generate new token pair
const newTokens = generateNewTokenPair(tokenData.user);
res.json(newTokens);
});Additional security measures for Bearer Token systems:
- Token binding: Bind tokens to specific user agents, IP addresses, or device fingerprints
- Short lifetimes: Use short-lived access tokens (5-15 minutes) with refresh tokens for continued access
- Revocation lists: Maintain server-side revocation lists for critical tokens
- Secure storage: Store tokens in HttpOnly cookies or secure storage mechanisms
middleBrick's remediation guidance provides specific recommendations based on the detected vulnerability patterns, including code examples and configuration changes tailored to your Bearer Token implementation.