Privilege Escalation in Adonisjs
Privilege Escalation in AdonisJS
Privilege escalation in AdonisJS occurs when an attacker exploits flaws in access control logic to gain higher-privilege permissions than intended. This typically manifests through improper authorization checks in route handlers or controller methods where user roles are not validated against the required permissions. For example, if a route is protected by a policy that checks auth.user.role === 'admin' but the condition is mistakenly written as auth.user.role !== 'guest', a low-privilege user could bypass the restriction.
Common AdonisJS-specific attack vectors include:
- Missing role/policy checks in
Authorization::policyconfigurations - Insecure
HttpContext.auth.useraccess patterns without validation - Improper use of
auth.asPasswordorauth.authenticatorwithout session integrity verification - Failure to validate ownership of entities in
Database.queryBuilderwhen usingwhereclauses
For instance, consider a user profile update endpoint that should only allow the owner to modify their own record. If the controller uses:
return await User.findOrFail(auth.user.id).then(user => {
return user.update(request.all())
})
An attacker could manipulate auth.user.id via request headers if the application does not enforce ownership checks beyond the initial authentication. A more secure pattern would validate that the authenticated user's ID matches the resource owner before processing:
const resource = await User.findOrFail(request.param('id'))
if (resource.userId !== auth.user.id) {
return response.status(403).send({ error: 'Unauthorized' })
}
return await resource.update(request.all())
Another critical vector is mass assignment vulnerabilities where sensitive fields like isAdmin or permissions are inadvertently updated through request payloads. AdonisJS mitigates this via fillable and hidden attributes in model definitions, but improper usage can still lead to escalation:
// Vulnerable model
const User = Schema.create({
username: { type: Schema.types.String, required: true },
isAdmin: { type: Schema.types.Boolean, default: false } // No protection
})
// In controller, using request.all() allows attackers to set isAdmin=true
Proper remediation requires defining fillable attributes and using AdonisJS's query builder methods that enforce field restrictions:
const User = Schema.create({
username: { type: Schema.types.String, required: true },
isAdmin: { type: Schema.types.Boolean, default: false, hidden: true }
})
// Safe update using validated fields only
const payload = await request.validate({
role: { rules: { in: ['admin', 'user'] }, role: 'string' }
})
if (!payload.role) {
return response.status(400).send({ error: 'Role required' })
}
const user = await User.findOrFail(request.param('id'))
if (payload.role === 'admin' && !auth.user.isAdmin) {
return response.status(403).send({ error: 'Insufficient permissions' })
}
user.role = payload.role
await user.save()
middleBrick helps detect such escalation risks by scanning AdonisJS endpoints for missing authorization checks and insecure data handling patterns. When analyzing a route like /api/users/:id, middleBrick checks whether the controller method validates resource ownership and role-based permissions against AdonisJS's built-in policy system. It also identifies cases where request payloads may modify sensitive fields without proper fillable constraints.
Through its OWASP API Top 10 integration, middleBrick specifically targets Broken Object Level Authorization (BOLA) and Insecure Direct Object References (IDOR), which are common precursors to privilege escalation. The scanner flags endpoints that accept object identifiers without verifying user ownership or role alignment, and it correlates these findings with AdonisJS-specific code structures such as controller methods and model definitions.
Detecting AdonisJS Privilege Escalation with middleBrick
middleBrick performs black-box scanning of AdonisJS endpoints to identify privilege escalation risks without requiring authentication or configuration. When scanning an AdonisJS application, it analyzes HTTP response patterns and request handling logic to detect missing authorization checks.
For example, consider an endpoint /api/orders/:id that should only allow the order owner to update it. middleBrick sends a request as an unauthenticated user and checks whether the response includes sensitive data without proper access controls. If the endpoint returns order details even when the user ID in the request does not match the owner, middleBrick flags this as a potential IDOR vulnerability that could lead to privilege escalation.
During scanning, middleBrick runs 12 security checks in parallel, including the BOLA/IDOR check. It specifically looks for:
- Absence of
if (resource.ownerId !== auth.user.id)validation patterns - Direct use of
request.param('id')without ownership verification - Improper use of
auth.asPasswordwithout session binding - Mass assignment risks via unprotected request fields
These findings are mapped to AdonisJS-specific code paths. For instance, if a route uses Route.get('users/:id', 'UserController.show') and the controller method accesses User.findOrFail(params.id) without checking resource.userId, middleBrick flags this as a high-risk finding. The scanner also identifies cases where sensitive fields like isAdmin are updated via request payloads without fillable restrictions.
middleBrick provides actionable findings with remediation guidance tailored to AdonisJS. For example, it might suggest adding a policy check in Authorization::policy or implementing ownership validation in the controller. The scan output includes specific line references to potential problem areas in the application logic, enabling developers to locate and fix issues efficiently.
AdonisJS-Specific Remediation Strategies
Remediation of privilege escalation vulnerabilities in AdonisJS requires leveraging the framework's built-in security features and following established patterns for access control.
Key remediation steps include:
- Implementing role-based access control (RBAC) using AdonisJS policies
- Enforcing field restrictions via model
fillableandhiddenattributes - Validating resource ownership before processing requests
- Using AdonisJS's built-in authentication guards for session integrity
For example, defining a policy for user resources:
// start/policies/userPolicy.js
const Policy = use('App/Policies/UserPolicy')
Policy.macros.register('hasRole', function (role) {
return function (user) {
return user.role === role
}
})
// policies/UserPolicy.js
class UserPolicy {
static get allows () {
return {
update: 'auth.user.id === params.id && auth.user.role === "admin"',
delete: 'auth.user.id === params.id && auth.user.role === "admin"'
}
}
}
module.exports = UserPolicy
Then, applying the policy in routes:
// start/routes.js
Route.put('users/:id', 'UserController.update').middleware('auth')
.use('policy:user.update')
This approach ensures that only authenticated admins can update user records, and the policy automatically validates the conditions before executing the controller method.
Another critical practice is using AdonisJS's query builder with explicit field selection to prevent mass assignment:
// models/User.js
const User = Schema.create({
username: { type: Schema.types.String, required: true },
role: { type: Schema.types.String, default: 'user', hidden: true }
})
// Safe update with validation
const payload = await request.validate({
role: { rules: { in: ['admin', 'user'] }, role: 'string' }
})
const user = await User.findOrFail(params.id)
if (auth.user.role !== 'admin') {
return response.status(403).send({ error: 'Insufficient permissions' })
}
user.role = payload.role
await user.save()
middleBrick supports these remediation efforts by identifying specific vulnerabilities and providing targeted guidance. For instance, if middleBrick detects that an endpoint accepts request.all() without field restrictions, it will recommend adding fillable attributes to models and using parameterized queries. The scanner also flags cases where sensitive operations lack proper authorization checks, helping developers align their code with OWASP API Top 10 standards for Broken Object Level Authorization.