HIGH time of check time of usebearer tokens

Time Of Check Time Of Use with Bearer Tokens

How Time Of Check Time Of Use Manifests in Bearer Tokens

Time Of Check Time Of Use (TOCTOU) vulnerabilities in Bearer Token systems occur when an application validates a token's permissions or state at one point in time, but the underlying authorization context changes before the token is actually used. This race condition creates a window where an attacker can exploit stale permissions or revoked access.

Consider a typical Bearer Token authentication flow where a user requests access to a resource:

GET /api/documents/12345 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

The server validates the token, checks permissions, and then processes the request. If the permission check and resource access aren't atomic, an attacker can exploit the gap.

Common Bearer Token TOCTOU scenarios include:

  • Permission revocation race: User has admin rights when token is issued, but admin role is revoked before token use
  • Document ownership changes: User can access a document during validation, but ownership changes before access
  • Subscription state changes: Premium feature access validated, but subscription expires mid-request

Here's a vulnerable implementation showing TOCTOU in action:

// VULNERABLE: Non-atomic permission check and access
async function getDocument(req, res) {
  const token = req.headers.authorization.split(' ')[1];
  const user = await validateBearerToken(token);
  
  // Time gap: permissions checked here
  if (!user.hasPermission('read_document', req.params.id)) {
    return res.status(403).json({error: 'Forbidden'});
  }
  
  // TOCTOU window: permissions could change here
  const document = await Document.findById(req.params.id);
  
  // Another gap: ownership could change before access
  if (document.ownerId !== user.id) {
    return res.status(403).json({error: 'Forbidden'});
  }
  
  return res.json(document);
}

The vulnerability exists because permission validation and resource access are separate operations. An attacker can exploit this by timing their requests to coincide with permission changes.

Bearer Tokens-Specific Detection

Detecting TOCTOU vulnerabilities in Bearer Token systems requires analyzing both the authentication flow and the authorization logic. middleBrick's black-box scanning approach tests the unauthenticated attack surface to identify these race conditions without requiring access to source code.

middleBrick scans for Bearer Token TOCTOU by:

  • Testing token validation timing against permission changes
  • Checking for non-atomic authorization patterns
  • Identifying endpoints where permissions are cached or stored in session state
  • Analyzing response timing to detect race condition windows

Manual detection techniques for Bearer Token TOCTOU include:

// Test for TOCTOU by rapidly changing permissions
async function testTOCTOU(endpoint, token) {
  const results = [];
  
  // Phase 1: Get initial permissions
  const initialResponse = await fetch(endpoint, {
    headers: {Authorization: `Bearer ${token}`}
  });
  results.push(initialResponse.status);
  
  // Phase 2: Rapidly change permissions during request
  const permissionChangePromise = changeUserPermissions(token, 'revoke');
  const responseDuringChange = await fetch(endpoint, {
    headers: {Authorization: `Bearer ${token}`}
  });
  results.push(responseDuringChange.status);
  
  // Phase 3: Verify final state
  await permissionChangePromise;
  const finalResponse = await fetch(endpoint, {
    headers: {Authorization: `Bearer ${token}`}
  });
  results.push(finalResponse.status);
  
  return results;
}

Key indicators of Bearer Token TOCTOU vulnerabilities:

IndicatorWhat to Look ForRisk Level
Non-atomic permission checksSeparate validation and access operationsHigh
Cached authorization statePermissions stored in memory or cache without refreshHigh
Stale token validationToken claims checked once at authenticationMedium
Time-delayed authorizationPermission checks that take variable timeMedium

middleBrick's Bearer Token-specific checks include validation of JWT claims freshness, detection of cached permission states, and analysis of authorization flow atomicity. The scanner tests 12 security categories including authentication bypasses and privilege escalation patterns specific to token-based systems.

Bearer Tokens-Specific Remediation

Remediating TOCTOU vulnerabilities in Bearer Token systems requires making authorization checks atomic and ensuring permission validation happens at the moment of resource access. Here are Bearer Token-specific fixes:

1. Atomic Permission Validation Pattern:

// SECURE: Atomic check-and-access pattern
async function getDocumentAtomic(req, res) {
  const token = req.headers.authorization.split(' ')[1];
  const user = await validateBearerToken(token);
  const documentId = req.params.id;
  
  // Single atomic operation: validate and retrieve
  const result = await db.collection('documents').findOne({
    _id: documentId,
    $or: [
      { ownerId: user.id },
      { sharedWith: user.id },
      { 'permissions.users': { $elemMatch: { userId: user.id, access: 'read' } } }
    ]
  });
  
  if (!result) {
    return res.status(403).json({error: 'Forbidden or not found'});
  }
  
  return res.json(result);
}

2. JWT Claim Refresh Pattern:

// SECURE: Refresh claims before each sensitive operation
async function secureOperation(req, res) {
  const token = req.headers.authorization.split(' ')[1];
  
  // Refresh token claims to get current permissions
  const freshClaims = await refreshBearerTokenClaims(token);
  
  // Validate current permissions
  if (!freshClaims.permissions.includes('sensitive_operation')) {
    return res.status(403).json({error: 'Insufficient permissions'});
  }
  
  // Perform operation with verified current permissions
  await performSensitiveOperation(freshClaims.userId);
  return res.json({success: true});
}

3. Database-Level Authorization:

// SECURE: Database enforces authorization
async function databaseLevelAuth(req, res) {
  const token = req.headers.authorization.split(' ')[1];
  const user = await validateBearerToken(token);
  const documentId = req.params.id;
  
  try {
    // Database checks ownership and permissions atomically
    const result = await db.query(`
      SELECT * FROM documents 
      WHERE id = $1 
      AND (owner_id = $2 OR 
           EXISTS (SELECT 1 FROM document_permissions 
                   WHERE document_id = $1 AND user_id = $2 AND access = 'read'))
    `, [documentId, user.id]);
    
    if (result.rows.length === 0) {
      return res.status(403).json({error: 'Forbidden'});
    }
    
    return res.json(result.rows[0]);
  } catch (error) {
    return res.status(500).json({error: 'Database error'});
  }
}

4. Permission Versioning Pattern:

// SECURE: Versioned permissions prevent stale access
class PermissionManager {
  async checkPermissionAtomic(userId, permission, resourceId) {
    // Get current permission version
    const currentVersion = await this.getPermissionVersion(resourceId);
    
    // Validate permission with version check
    const permissionRecord = await db.collection('permissions').findOne({
      userId,
      resourceId,
      permission,
      version: currentVersion
    });
    
    if (!permissionRecord) {
      throw new Error('Permission denied or stale');
    }
    
    return true;
  }
}

Best practices for Bearer Token TOCTOU prevention:

  • Always validate permissions at the moment of resource access, not at authentication
  • Use database-level authorization checks when possible
  • Implement permission versioning to detect stale access attempts
  • Refresh JWT claims before sensitive operations
  • Make authorization checks and resource access a single atomic operation

middleBrick's remediation guidance for Bearer Token TOCTOU includes specific code patterns for atomic authorization, JWT claim management, and database-level permission enforcement. The scanner identifies vulnerable patterns and provides actionable fixes tailored to Bearer Token implementations.

Frequently Asked Questions

How does Time Of Check Time Of Use differ between JWT and opaque Bearer Tokens?
JWT tokens often exacerbate TOCTOU because claims are validated once at authentication and then cached, while opaque tokens typically require database lookups for each request. JWT TOCTOU is more common because developers assume claims are always current. Opaque tokens can still have TOCTOU if the token validation and permission check are separate operations. middleBrick tests both patterns for race condition vulnerabilities.
Can rate limiting help prevent Bearer Token TOCTOU attacks?
Rate limiting alone cannot prevent TOCTOU vulnerabilities because the issue is about authorization timing, not request frequency. However, rate limiting can make TOCTOU attacks more difficult by reducing the window for timing-based exploitation. The proper fix is atomic authorization checks. middleBrick's rate limiting checks identify whether your API has appropriate limits, but TOCTOU requires specific authorization pattern fixes.