HIGH timing attackadonisjs

Timing Attack in Adonisjs

How Timing Attack Manifests in Adonisjs

Timing attacks in Adonisjs applications exploit the time differences between successful and failed authentication attempts, password comparisons, or database queries. These attacks allow malicious actors to infer sensitive information by measuring response times.

The most common manifestation occurs in authentication middleware. Adonisjs's built-in auth system uses bcrypt for password hashing, but if you implement custom authentication logic, you might inadvertently introduce timing vulnerabilities. Consider this problematic Adonisjs controller code:

class AuthController {
  async login({ request, auth }) {
    const { email, password } = request.all()
    const user = await User.query().where('email', email).first()
    
    if (user && await compare(password, user.password)) {
      return auth.generate(user)
    }
    
    return response.status(401).send('Invalid credentials')
  }
}

The vulnerability here is subtle but critical. When a user exists but provides an incorrect password, the compare() function still executes, taking measurable time. When a user doesn't exist, the function returns immediately. An attacker can measure these timing differences to determine which emails are registered.

Another Adonisjs-specific timing attack vector appears in route parameter validation. Adonisjs's Lucid ORM query builder can leak timing information through different query execution paths:

async show({ params }) {
  const user = await User.find(params.id)
  
  if (!user) {
    return response.status(404).send('User not found')
  }
  
  return user
}

This code leaks information through database query timing. A valid ID returns faster than an invalid one because the database engine processes them differently. An attacker can exploit this to enumerate valid IDs and discover the total number of records.

Adonisjs's middleware system can also introduce timing leaks if not implemented carefully. Consider this authorization middleware:

async handle({ auth, params }, next) {
  const user = await auth.getUser()
  const resource = await Resource.find(params.resourceId)
  
  if (!resource) {
    return response.status(404).send('Resource not found')
  }
  
  if (resource.owner_id !== user.id) {
    return response.status(403).send('Access denied')
  }
  
  await next()
}

This middleware leaks whether a resource exists through timing differences, allowing attackers to map out valid resource IDs even when they don't have permission to access them.

Adonisjs-Specific Detection

Detecting timing attacks in Adonisjs applications requires both manual code review and automated scanning. middleBrick's API security scanner includes specific checks for timing vulnerabilities in Adonisjs applications.

For manual detection, use a timing analysis tool to measure response variations. Here's how to test your Adonisjs endpoints:

const axios = require('axios')
const { performance } = require('perf_hooks')

async function testTiming(url, iterations = 100) {
  const timings = []
  
  for (let i = 0; i < iterations; i++) {
    const start = performance.now()
    try {
      await axios.post(url, {
        email: i % 2 === 0 ? 'valid@example.com' : 'invalid@example.com',
        password: 'wrongpassword'
      })
    } catch (error) {
      // Ignore errors, we're measuring timing
    }
    const end = performance.now()
    timings.push(end - start)
  }
  
  const avg = timings.reduce((a, b) => a + b) / timings.length
  const variance = timings.reduce((sum, val) => sum + Math.pow(val - avg, 2), 0) / timings.length
  
  console.log(`Average: ${avg.toFixed(2)}ms, Variance: ${variance.toFixed(2)}ms`)
}

// Test your Adonisjs auth endpoint
testTiming('http://localhost:3333/api/auth/login')

middleBrick scans for timing attack vulnerabilities by analyzing your Adonisjs application's response patterns. It tests authentication endpoints with valid and invalid credentials, measuring statistical timing differences. The scanner also examines your OpenAPI/Swagger spec to identify endpoints that should have constant-time responses.

middleBrick's LLM security features are particularly relevant for Adonisjs applications using AI integrations. It tests for prompt injection vulnerabilities that could leak timing information through AI model responses, and checks for excessive agency patterns that might expose timing-sensitive operations.

The scanner provides a security score with detailed findings, showing you exactly which endpoints are vulnerable and what the timing variance is. It prioritizes findings based on severity and provides specific remediation guidance for Adonisjs applications.

Adonisjs-Specific Remediation

Remediating timing attacks in Adonisjs requires implementing constant-time operations and eliminating information leakage through response timing. Here are Adonisjs-specific solutions:

For authentication, always perform the same operations regardless of whether the user exists. Use Adonisjs's built-in auth system or implement constant-time comparison:

const crypto = require('crypto')

class AuthController {
  async login({ request, auth, response }) {
    const { email, password } = request.all()
    let user
    let validPassword = false
    
    // Always query for the user to maintain consistent timing
    user = await User.query().where('email', email).first()
    
    if (user) {
      validPassword = await compare(password, user.password)
    }
    
    // Always perform a dummy comparison to equalize timing
    const dummyHash = '$2b$10$abcdefghijklmnopqrstuv' // 24 chars
    await compare(password, dummyHash)
    
    if (user && validPassword) {
      return auth.generate(user)
    }
    
    // Use a constant-time delay to equalize response times
    const start = performance.now()
    while (performance.now() - start < 100) {
      // Busy wait for 100ms
    }
    
    return response.status(401).send('Invalid credentials')
  }
}

For resource access, implement constant-time existence checks:

async handle({ auth, params }, next) {
  const user = await auth.getUser()
  const resourceId = params.resourceId
  
  // Always perform the same database operations
  const [resource, dummy] = await Promise.all([
    Resource.find(resourceId),
    Resource.query().where('owner_id', user.id).limit(1).first()
  ])
  
  // Always perform authorization checks even if resource doesn't exist
  const hasAccess = resource ? resource.owner_id === user.id : false
  const dummyCheck = dummy ? dummy.owner_id === user.id : false
  
  // Use a constant-time decision
  const authorized = hasAccess || dummyCheck
  
  if (!authorized) {
    return response.status(403).send('Access denied')
  }
  
  await next()
}

middleBrick's CLI tool helps you verify these fixes:

npm install -g middlebrick
middlebrick scan http://localhost:3333/api/auth/login --profile adonisjs

This command runs Adonisjs-specific timing attack detection, checking your authentication and authorization endpoints for constant-time vulnerabilities. The GitHub Action integration allows you to fail builds if timing attack vulnerabilities are detected:

name: API Security Scan
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run middleBrick Scan
        run: |
          npx middlebrick scan http://localhost:3333 --fail-on-severity=high

For applications using Adonisjs's AI features, middleBrick's MCP Server integration allows you to scan APIs directly from your IDE while coding, providing real-time feedback on timing attack vulnerabilities as you implement authentication and authorization logic.

Frequently Asked Questions

How can I test if my Adonisjs authentication endpoint is vulnerable to timing attacks?
Use a timing analysis tool to measure response times for valid vs invalid credentials. A vulnerable endpoint will show statistically significant timing differences. middleBrick's scanner automates this by testing your endpoints with thousands of requests and analyzing the timing variance.
Does Adonisjs's built-in auth system protect against timing attacks?
Adonisjs's built-in auth system uses bcrypt for password comparison, which is designed to be timing-safe. However, the surrounding authentication logic (user lookup, response handling) can still introduce timing leaks. Always test your complete authentication flow with timing analysis tools.