HIGH adonisjsidor enumeration

Idor Enumeration in Adonisjs

How Idor Enumeration Manifests in Adonisjs

In Adonisjs applications, IDOR enumeration commonly occurs when developers rely on sequential numeric IDs in route parameters without implementing proper authorization checks. A typical pattern involves resource endpoints like GET /users/:id or GET /orders/:id where the :id parameter is used directly to fetch database records without verifying if the authenticated user owns or is permitted to access that resource.

Adonisjs-specific manifestations include:

  • Controllers using param('id') from the HttpContext to query models via User.find() or Order.find() without ownership validation
  • Route definitions in start/routes.ts that expose numeric IDs (e.g., Route.get('users/:id', 'UsersController.show')) lacking middleware for authorization
  • Use of Adonisjs Lucid ORM's find() or first() methods that return records based solely on ID, bypassing relational checks
  • Pagination or listing endpoints where limit and offset parameters are manipulated to enumerate through ID ranges (e.g., /api/posts?limit=1&offset=1000)

Attackers enumerate IDs by incrementing or decrementing values (e.g., trying /api/invoices/1, /api/invoices/2, etc.) to access unauthorized data. This is particularly effective in Adonisjs apps using auto-incrementing primary keys, which is the default in Lucid migrations. Real-world analogues include CVE-2020-13942 (IDOR in a healthcare API) and OWASP API1:2023 Broken Object Level Authorization.

Adonisjs-Specific Detection

Detecting IDOR enumeration in Adonisjs requires examining both route exposure and controller logic. middleBrick identifies this through black-box testing of the unauthenticated or low-privilege attack surface by:

  • Probing endpoints with numeric ID parameters (e.g., /api/v1/users/1, /api/v1/users/2) and comparing responses for sensitive data leakage
  • Detecting patterns where sequential ID access returns 200 OK with PII, financial data, or proprietary information without corresponding authentication challenges
  • Analyzing OpenAPI/Swagger specs (if present) to identify routes with :id path parameters lacking security schemas or authorization requirements
  • Testing for enumeration via parameter manipulation in query strings (e.g., ?user_id=1) or headers that Adonisjs controllers might inadvertently use

For example, if an Adonisjs route GET /api/v1/profile/:id returns a user's email and phone number when accessed with id=5 by an unauthenticated user, middleBrick flags this as a high-severity IDOR finding. The scanner cross-references runtime responses with spec definitions to confirm whether the endpoint should be restricted. Detection focuses on behavior: if accessing id=N+1 returns data belonging to another user, it confirms enumeration viability. middleBrick does not assume framework internals; it observes responses to crafted requests, making it effective against custom Adonisjs implementations.

Adonisjs-Specific Remediation

Remediating IDOR enumeration in Adonisjs involves enforcing authorization at the controller or middleware level using Adonisjs's built-in features. Key strategies include:

  • Using Adonisjs middleware to verify resource ownership before proceeding
  • Implementing policy checks with Adonisjs's authorizer (via @ioc:Adonis/Addons/Bouncer) or custom guards
  • Avoiding direct use of param('id') for access control; instead, scope queries to the authenticated user's context

Example: Fixing a vulnerable UsersController.show method

// app/Controllers/Http/UsersController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'

public async show({ params, auth, response }: HttpContextContract) {
  // Remediation 1: Use authenticated user's ID instead of params.id
  const user = await User.findOrFail(auth.user?.id)
  return response.ok(user)
}

For cases where resource access depends on the ID parameter (e.g., admin viewing any user):

// app/Controllers/Http/UsersController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'

public async show({ params, auth, bouncer, response }: HttpContextContract) {
  // Remediation 2: Authorize using Bouncer before fetching
  await bouncer.with('UserPolicy').authorize('view', auth.user)
  const user = await User.findOrFail(params.id)
  return response.ok(user)
}

Define the policy in start/policy.ts:

// start/policy.ts
import { BouncerContract } from '@ioc:Adonis/Addons/Bouncer'
import User from 'App/Models/User'

const userPolicy = bouncer => {
  bouncer.define('UserPolicy', (user, targetUser) => {
    // Allow if user is admin OR viewing own profile
    return user.isAdmin || user.id === targetUser.id
  })
}

export default { userPolicy }

Alternative: Scope the query to prevent enumeration even if ID is guessed

// app/Controllers/Http/OrdersController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Order from 'App/Models/Order'

public async index({ auth, request, response }: HttpContextContract) {
  // Remediation 3: Never expose raw IDs; scope to user
  const page = request.input('page', 1)
  const limit = request.input('limit', 10)
  
  const orders = await Order.query()
    .where('user_id', auth.user?.id)
    .paginate(page, limit)
  
  return response.ok(orders)
}

These approaches leverage Adonisjs's native authentication, authorization, and ORM capabilities to ensure users only access permitted resources, eliminating IDOR enumeration vectors.

Frequently Asked Questions

Does middleBrick require access to my Adonisjs source code to detect IDOR enumeration?
No, middleBrick performs black-box scanning by submitting requests to your API endpoint. It detects IDOR through behavioral analysis of responses (e.g., accessing sequential IDs returns unauthorized data) without needing source code, agents, or configuration.
Can using UUIDs instead of numeric IDs in Adonisjs prevent IDOR enumeration?
Using UUIDs makes enumeration harder due to the large keyspace, but it does not eliminate IDOR if authorization checks are missing. An attacker who guesses or obtains a UUID can still access unauthorized data. Proper authorization (as shown in the remediation examples) is required regardless of ID type.