HIGH privilege escalationhapi

Privilege Escalation in Hapi

How Privilege Escalation Manifests in Hapi

Privilege escalation in Hapi applications often occurs through improper authentication and authorization boundaries. The most common pattern involves route-level authentication that doesn't properly cascade to nested route handlers or middleware. Consider this vulnerable pattern:

const Hapi = require('@hapi/hapi');
const server = Hapi.server({ port: 3000 });

// Admin-only route
const adminRoute = {
  method: 'GET',
  path: '/admin/users',
  options: {
    auth: 'admin-strategy'
  },
  handler: async (request, h) => {
    const users = await request.db.users.find();
    return users;
  }
};

server.route(adminRoute);

// Nested route without auth
const nestedRoute = {
  method: 'GET',
  path: '/admin/users/{id}',
  options: {},
  handler: async (request, h) => {
    const user = await request.db.users.findById(request.params.id);
    return user;
  }
};

server.route(nestedRoute);

The nested route inherits no authentication context from its parent path, allowing any authenticated user to access admin user data. Hapi's route isolation means nested routes are completely independent unless explicitly configured.

Another Hapi-specific escalation vector involves plugin scope leakage. When plugins register routes without proper scope isolation, they can access higher-privilege context:

const plugin = {
  name: 'user-plugin',
  version: '1.0.0',
  register: async (server, options) => {
    // Plugin has access to server.app.adminContext
    server.route({
      method: 'GET',
      path: '/plugin/admin-data',
      handler: async (request, h) => {
        return request.server.app.adminContext.getAll();
      }
    });
  }
};

server.register(plugin);

This occurs when plugins are registered with insufficient sandboxing, allowing them to access administrative context objects stored in server.app.

Context injection through Hapi's request lifecycle is another escalation path. Malicious plugins or middleware can inject privileged objects into the request lifecycle:

// Vulnerable context injection
const injectAdminContext = (request, h) => {
  if (request.query.debug === 'true') {
    request.adminContext = request.server.app.adminContext;
  }
  return h.continue;
};

server.ext('onRequest', injectAdminContext);

An attacker can trigger debug mode and gain access to admin context through a simple query parameter.

Hapi-Specific Detection

Detecting privilege escalation in Hapi requires examining route configurations, plugin boundaries, and authentication strategies. The most effective approach combines static analysis with runtime scanning.

Static analysis should verify that all routes requiring elevated privileges have proper authentication strategies defined. Use this pattern to audit your routes:

const auditRoutes = (server) => {
  const routes = server.table().routes;
  const findings = [];
  
  routes.forEach(route => {
    if (route.path.includes('admin') || route.path.includes('privileged')) {
      if (!route.settings.auth || route.settings.auth === false) {
        findings.push({
          path: route.path,
          method: route.method,
          issue: 'Missing authentication on privileged route'
        });
      }
    }
  });
  
  return findings;
};

This identifies routes with admin-related paths that lack authentication requirements.

For runtime detection, middleBrick's black-box scanning can identify privilege escalation vulnerabilities by testing unauthenticated access to protected endpoints. The scanner attempts to access admin routes without credentials and analyzes responses:

# Scan your Hapi API with middleBrick
middlebrick scan https://yourapi.com --category "Privilege Escalation"

The scan tests for:

  • Unauthenticated access to admin routes
  • Authentication bypass through parameter manipulation
  • Context injection vulnerabilities
  • Plugin boundary violations

middleBrick's OpenAPI analysis also examines your Hapi-generated OpenAPI spec for missing authentication requirements on sensitive endpoints. The scanner cross-references your spec with actual runtime behavior to identify discrepancies.

Plugin boundary analysis is critical for Hapi applications. Use this diagnostic to verify plugin isolation:

const checkPluginBoundaries = (server) => {
  const plugins = server.plugins;
  const findings = [];
  
  Object.keys(plugins).forEach(pluginName => {
    const plugin = plugins[pluginName];
    if (plugin.exports && plugin.exports.adminContext) {
      findings.push({
        plugin: pluginName,
        issue: 'Plugin exports privileged context'
      });
    }
  });
  
  return findings;
};

This identifies plugins that improperly expose administrative functionality.

Hapi-Specific Remediation

Remediating privilege escalation in Hapi requires a defense-in-depth approach using Hapi's built-in security features. Start with route-level authentication that cannot be bypassed:

const adminRoute = {
  method: 'GET',
  path: '/admin/users',
  options: {
    auth: {
      strategy: 'admin-strategy',
      access: {
        scope: ['admin']
      }
    },
    pre: [
      // Verify admin scope before route handler
      (request, h) => {
        if (!request.auth.credentials.scope.includes('admin')) {
          throw Boom.forbidden('Admin privileges required');
        }
        return h.continue;
      }
    ]
  },
  handler: async (request, h) => {
    const users = await request.db.users.find();
    return users;
  }
};

This pattern combines strategy authentication with explicit scope checking and pre-handler validation.

For nested routes, use Hapi's route configuration inheritance properly. Define parent routes with authentication and ensure nested routes respect this context:

const adminParentRoute = {
  method: 'GET',
  path: '/admin/{p*}',
  options: {
    auth: 'admin-strategy',
    handler: (request, h) => {
      // Parent route handler can handle multiple sub-paths
      const segments = request.params.p.split('/');
      if (segments[0] === 'users') {
        return handleUsers(request);
      }
      throw Boom.notFound();
    }
  }
};

This eliminates the need for separate nested routes that might miss authentication.

Plugin isolation requires explicit scope boundaries. Use Hapi's plugin options to restrict access:

const securePlugin = {
  name: 'user-plugin',
  version: '1.0.0',
  options: {
    once: true,
    routes: {
      prefix: '/plugin',
      vhost: 'plugin.yourapp.com'
    }
  },
  register: async (server, options) => {
    // Plugin has restricted scope
    server.route({
      method: 'GET',
      path: '/plugin/data',
      options: {
        auth: 'user-strategy',
        pre: [
          (request, h) => {
            // Validate plugin context
            if (!request.server.app.pluginContext) {
              throw Boom.internal('Invalid plugin context');
            }
            return h.continue;
          }
        ]
      },
      handler: async (request, h) => {
        return request.server.app.pluginContext.getData();
      }
    });
  }
};

This pattern restricts plugin routes to specific prefixes and vhosts, preventing scope leakage.

Context injection vulnerabilities require strict input validation. Never expose privileged context based on query parameters:

const secureContextInjection = (request, h) => {
  // Never expose admin context based on user input
  if (request.query.debug) {
    throw Boom.badRequest('Debug mode not available');
  }
  return h.continue;
};

server.ext('onRequest', secureContextInjection);

Implement comprehensive logging for privilege escalation attempts:

const auditLogger = (request, h) => {
  if (request.path.includes('admin') && !request.auth.isAuthenticated) {
    request.logger.error('Privilege escalation attempt', {
      path: request.path,
      ip: request.info.remoteAddress,
      userAgent: request.headers['user-agent']
    });
  }
  return h.continue;
};

server.ext('onRequest', auditLogger);

This creates an audit trail for suspicious access patterns.

Frequently Asked Questions

How does middleBrick detect privilege escalation in Hapi APIs?
middleBrick performs black-box scanning of your Hapi API endpoints, testing for unauthenticated access to admin routes, authentication bypass attempts, and context injection vulnerabilities. The scanner analyzes your OpenAPI spec for missing authentication requirements and compares it with actual runtime behavior to identify discrepancies. It also tests plugin boundaries by attempting to access routes that should be restricted to specific scopes or vhosts.
What's the difference between authentication and authorization in Hapi privilege escalation?
Authentication verifies who the user is (admin vs regular user), while authorization determines what they can access. In Hapi, you can have authentication without proper authorization, which creates escalation risks. For example, a route might authenticate users correctly but fail to check if they have the 'admin' scope before returning sensitive data. Always implement both: authentication strategies to verify identity, and authorization checks (like scope validation) to enforce access boundaries.