HIGH bola idoradonisjs

Bola Idor in Adonisjs

How Bola Idor Manifests in Adonisjs

BOLA (Broken Object Level Authorization) and IDOR (Insecure Direct Object Reference) vulnerabilities in Adonisjs applications typically arise from improper authorization checks when accessing user-specific resources. In Adonisjs, these vulnerabilities often manifest in controller methods that directly use request parameters without verifying the authenticated user's permissions.

Consider a typical Adonisjs controller pattern:

class UserController {
  async show({ params, auth }) {
    const user = await User.find(params.id)
    return user
  }
}

This code has a critical BOLA vulnerability. Any authenticated user can access /users/1, /users/2, etc., regardless of whether they own that user record. The controller fetches the user by ID without checking if the authenticated user has permission to view that specific resource.

Another common Adonisjs pattern that enables IDOR:

class PostController {
  async update({ params, request, auth }) {
    const post = await Post.find(params.id)
    post.merge(request.post())
    await post.save()
    return post
  }
}

Here, any authenticated user can modify any post by simply knowing its ID. Adonisjs's Lucid ORM makes it trivial to fetch records without authorization checks, creating a perfect storm for BOLA vulnerabilities.

Route binding in Adonisjs can also introduce BOLA if not properly secured:

Route.resource('users.posts', 'PostController').apiOnly()

Without proper middleware or authorization checks, this automatically generates routes like GET /users/:user_id/posts where any user could enumerate posts from other users' accounts by changing the user_id parameter.

Adonisjs's authentication system, while robust, doesn't automatically enforce authorization at the resource level. The framework provides authentication middleware but leaves authorization entirely to the developer, making it easy to accidentally expose resources.

Adonisjs-Specific Detection

Detecting BOLA/IDOR in Adonisjs applications requires both manual code review and automated scanning. middleBrick's black-box scanning approach is particularly effective for Adonisjs APIs because it tests the actual running application without needing source code access.

middleBrick scans Adonisjs APIs by sending authenticated requests to resource endpoints with manipulated IDs. For example, it might:

  • Log in as one user, then attempt to access /users/2, /users/3, etc.
  • Fetch a resource owned by the authenticated user, then modify the ID parameter to access other users' resources
  • Check for information disclosure by comparing responses from valid vs invalid IDs
  • Test for missing authorization by attempting actions on resources that should be inaccessible

The scanner specifically looks for Adonisjs patterns like:

Route.get('/users/:id', 'UserController.show')
Route.put('/posts/:id', 'PostController.update')
Route.delete('/comments/:id', 'CommentController.delete')

middleBrick's 12 security checks include Property Authorization testing that's particularly relevant for Adonisjs applications using Lucid models. The scanner verifies that sensitive fields (email, phone, address) aren't exposed to unauthorized users.

For Adonisjs applications with complex relationships, middleBrick tests nested resource access patterns:

// Vulnerable pattern middleBrick detects
async show({ params }) {
  const posts = await User.find(params.userId).posts().fetch()
  return posts
}

The scanner attempts to access /users/999/posts where 999 is a non-existent or foreign user ID, checking if the application properly handles unauthorized access attempts.

middleBrick also detects missing rate limiting, which often accompanies BOLA vulnerabilities in Adonisjs apps. Attackers can systematically enumerate user IDs if rate limiting isn't in place, making BOLA exploitation more practical.

Adonisjs-Specific Remediation

Remediating BOLA/IDOR in Adonisjs requires implementing proper authorization checks using the framework's built-in features. The most effective approach is using Adonisjs's Gate and Policy system, which provides a structured way to define authorization rules.

First, create a policy for your models:

import Post from 'App/Models/Post'
import User from 'App/Models/User'

export default class PostPolicy {
  async view(user: User, post: Post) {
    return post.userId === user.id
  }

  async update(user: User, post: Post) {
    return post.userId === user.id
  }

  async delete(user: User, post: Post) {
    return post.userId === user.id
  }
}

Then register the policy in your start/kernel.ts:

import { policies } from '@adonisjs/framework/src/Policy'
import PostPolicy from 'App/Policies/PostPolicy'

policies.set(Post, new PostPolicy())

Modify your controller to use the policy:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Post from 'App/Models/Post'
import { policies } from '@adonisjs/framework/src/Policy'

export default class PostController {
  async show({ params, auth }: HttpContextContract) {
    const post = await Post.findOrFail(params.id)
    
    if (!(await policies.can(auth.user!, 'view', post))) {
      return response.unauthorized()
    }
    
    return post
  }
}

For Adonisjs applications using route binding, implement a global authorization middleware:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { policies } from '@adonisjs/framework/src/Policy'

export default class AuthorizeResourceMiddleware {
  async handle({ params, auth, response }: HttpContextContract, next) {
    const resource = params.id
    const user = auth.user!
    
    if (resource && !(await policies.can(user, 'view', resource))) {
      return response.unauthorized()
    }
    
    await next()
  }
}

Register this middleware in start/kernel.ts and apply it to routes that need authorization.

Another Adonisjs-specific approach is using model hooks for authorization:

import Post from 'App/Models/Post'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

Post.addHook('beforeFetch', async (modelBuilder) => {
  const ctx = HttpContextContract.get()
  if (ctx && ctx.auth.isAuthenticated) {
    const user = ctx.auth.user!
    modelBuilder.where('user_id', user.id)
  }
})

This automatically scopes all Post queries to the authenticated user, preventing BOLA at the database level. However, this approach requires careful consideration as it affects all queries, including administrative ones.

For Adonisjs applications with complex authorization requirements, consider using the @adonisjs/acl package, which provides role-based access control that integrates well with the policy system.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

How does middleBrick specifically detect BOLA vulnerabilities in Adonisjs APIs?
middleBrick performs black-box scanning by sending authenticated requests with manipulated resource IDs to your Adonisjs API endpoints. It tests patterns like /users/:id, /posts/:id, and nested resources like /users/:user_id/posts by attempting to access resources owned by other users. The scanner checks if your Adonisjs application properly validates that the authenticated user has permission to access the requested resource, regardless of whether they know the ID. It also tests for information disclosure by comparing responses from valid vs invalid IDs and checks for missing authorization in controller methods that directly use request parameters without verification.
Can I integrate middleBrick scanning into my Adonisjs CI/CD pipeline?
Yes, you can integrate middleBrick into your Adonisjs CI/CD pipeline using the middleBrick GitHub Action. Add it to your workflow to automatically scan your Adonisjs API endpoints before deployment. The action can be configured to fail the build if the security score drops below your threshold, ensuring BOLA vulnerabilities and other security issues are caught before production deployment. This is particularly valuable for Adonisjs applications since the framework doesn't enforce authorization by default, making it easy to accidentally deploy BOLA vulnerabilities.