HIGH api rate abusehapi

Api Rate Abuse in Hapi

How Api Rate Abuse Manifests in Hapi

Api rate abuse in Hapi applications typically exploits missing or misconfigured rate limiting, allowing attackers to overwhelm server resources through excessive API calls. In Hapi, this vulnerability manifests in several ways:

// Vulnerable Hapi route without rate limiting
const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({ port: 3000 });

  server.route({
    method: 'GET',
    path: '/api/vulnerable',
    handler: (request, h) => {
      // No rate limiting - open to abuse
      return { data: 'sensitive information' };
    }
  });

  await server.start();
  console.log('Server running on %s', server.info.uri);
};

Attackers exploit this by sending thousands of requests per minute to endpoints like login, search, or data retrieval APIs. Common abuse patterns include:

  • Credential stuffing: Automated login attempts using stolen credentials
  • Enumeration attacks: Brute-forcing user IDs, tokens, or resource identifiers
  • Resource exhaustion: Flooding endpoints to consume CPU, memory, or database connections
  • Data scraping: Rapidly extracting content from unprotected endpoints

Hapi's plugin architecture makes it particularly vulnerable when developers forget to apply rate limiting to specific routes or plugin endpoints. For example, a plugin handling file uploads might expose an endpoint without proper throttling:

// Plugin without rate limiting
const FileUploadPlugin = {
  name: 'file-upload',
  version: '1.0.0',
  register: async (server) => {
    server.route({
      method: 'POST',
      path: '/upload',
      handler: async (request, h) => {
        const file = request.payload.file;
        // Process file without rate limiting
        return { success: true };
      }
    });
  }
};

Another Hapi-specific manifestation occurs with dynamic route generation. When routes are created programmatically based on database content or configuration files, developers might overlook applying consistent rate limiting policies:

// Dynamically generated routes missing rate limiting
const generateRoutes = async (server) => {
  const routes = await db.getRoutes();
  routes.forEach(route => {
    server.route({
      method: route.method,
      path: route.path,
      handler: route.handler
      // Missing rate limiting configuration
    });
  });
};

Hapi-Specific Detection

Detecting API rate abuse in Hapi requires both runtime monitoring and proactive scanning. Hapi provides several mechanisms for identifying rate abuse patterns:

// Hapi request logging for abuse detection
const Hapi = require('@hapi/hapi');
const Good = require('@hapi/good');

const init = async () => {
  const server = Hapi.server({ port: 3000 });

  await server.register({
    plugin: Good,
    options: {
      reporters: {
        console: [
          {
            module: '@hapi/good-console',
            args: [{ request: '*', response: '*' }]
          }
        ]
      }
    }
  });

  server.events.on('request', (request, event, tags) => {
    if (tags.error) {
      console.error('Request error:', event.error);
    }
  });
};

For comprehensive detection, middleBrick's API security scanner identifies rate abuse vulnerabilities through black-box testing of Hapi endpoints. The scanner tests for missing rate limiting by:

  • Sending rapid sequential requests to detect lack of throttling
  • Analyzing response patterns for inconsistent error handling
  • Checking for missing X-RateLimit headers in responses
  • Identifying endpoints that return different responses under load

middleBrick specifically tests Hapi applications by scanning the unauthenticated attack surface and checking for the 12 security categories, including rate limiting and input validation vulnerabilities. The scanner can detect when Hapi routes lack proper rate limiting configuration:

{
  "risk_score": 65,
  "category_breakdown": {
    "rate_limiting": "FAIL",
    "input_validation": "WARNING",
    "authentication": "PASS"
  },
  "findings": [
    {
      "severity": "HIGH",
      "title": "Missing Rate Limiting on /api/data endpoint",
      "description": "Endpoint allows unlimited requests without throttling",
      "remediation": "Implement rate limiting using @hapi/rate-limiting plugin"
    }
  ]
}

Additionally, Hapi's built-in request lifecycle events can be used to implement custom rate abuse detection:

// Custom rate abuse detection using Hapi events
const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({ port: 3000 });
  
  const requestCounts = new Map();
  
  server.ext('onRequest', (request, h) => {
    const ip = request.info.remoteAddress;
    const count = requestCounts.get(ip) || 0;
    
    if (count > 100) { // Threshold for suspicious activity
      console.warn(`Potential rate abuse from ${ip}: ${count} requests`);
    }
    
    requestCounts.set(ip, count + 1);
    return h.continue;
  });
};

Hapi-Specific Remediation

Remediating API rate abuse in Hapi requires implementing proper rate limiting using Hapi's plugin ecosystem. The most effective approach uses the @hapi/rate-limiting plugin:

// Proper rate limiting implementation in Hapi
const Hapi = require('@hapi/hapi');
const RateLimit = require('@hapi/rate-limiting');

const init = async () => {
  const server = Hapi.server({ port: 3000 });

  await server.register({
    plugin: RateLimit,
    options: {
      redis: {
        host: 'localhost',
        port: 6379
      },
      userLimit: 100, // 100 requests per user
      userCacheTimeout: 3600, // 1 hour
      ipLimit: 50, // 50 requests per IP
      ipCacheTimeout: 3600,
      userOptions: {
        cookie: 'session',
        header: 'authorization'
      }
    }
  });

  server.route({
    method: 'GET',
    path: '/api/secured',
    handler: (request, h) => {
      return { data: 'protected resource' };
    }
  });
};

For more granular control, Hapi's route-level rate limiting allows different policies per endpoint:

// Route-specific rate limiting
server.route({
  method: 'POST',
  path: '/api/login',
  options: {
    plugins: {
      'hapi-rate-limiting': {
        userLimit: 5, // Stricter limit for login
        userCacheTimeout: 300, // 5 minutes
        userOptions: {
          cookie: 'session',
          header: 'authorization'
        }
      }
    }
  },
  handler: (request, h) => {
    // Login logic
    return { success: true };
  }
});

Hapi's server extension points provide another remediation approach for implementing custom rate limiting logic:

// Custom rate limiting using server extensions
const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({ port: 3000 });
  
  const rateLimits = new Map();
  const WINDOW_SIZE = 60000; // 1 minute
  const MAX_REQUESTS = 100;

  server.ext('onRequest', (request, h) => {
    const key = request.info.remoteAddress;
    const windowStart = Math.floor(Date.now() / WINDOW_SIZE) * WINDOW_SIZE;
    const windowKey = `${key}:${windowStart}`;
    
    if (!rateLimits.has(windowKey)) {
      rateLimits.set(windowKey, 0);
    }
    
    const count = rateLimits.get(windowKey) + 1;
    rateLimits.set(windowKey, count);
    
    if (count > MAX_REQUESTS) {
      return h.response('Rate limit exceeded').code(429);
    }
    
    return h.continue;
  });
};

For distributed systems, combining Hapi with Redis-based rate limiting ensures consistent protection across multiple server instances:

// Distributed rate limiting with Redis
const Hapi = require('@hapi/hapi');
const Redis = require('redis');

const init = async () => {
  const redisClient = Redis.createClient({ host: 'redis-server' });
  const server = Hapi.server({ port: 3000 });

  server.ext('onRequest', async (request, h) => {
    const key = `rate-limit:${request.info.remoteAddress}`;
    const current = await redisClient.incr(key);
    
    if (current === 1) {
      await redisClient.expire(key, 60); // 1 minute window
    }
    
    if (current > 100) {
      return h.response('Too Many Requests').code(429);
    }
    
    return h.continue;
  });
};

Frequently Asked Questions

How does Hapi's rate limiting differ from Express or Fastify?
Hapi provides built-in plugin architecture that makes rate limiting more modular and configurable. Unlike Express middleware that wraps the entire app, Hapi plugins can be applied at route, plugin, or server level with fine-grained control. The @hapi/rate-limiting plugin integrates seamlessly with Hapi's request lifecycle and supports Redis for distributed environments out of the box.
Can middleBrick detect rate abuse vulnerabilities in Hapi applications?
Yes, middleBrick's black-box scanner tests Hapi endpoints for missing rate limiting by sending rapid sequential requests and analyzing responses. It checks for the absence of rate limit headers, inconsistent error responses under load, and endpoints that allow unlimited requests. The scanner provides specific findings with severity levels and remediation guidance tailored to Hapi applications.