HIGH broken access controlloopback

Broken Access Control in Loopback

How Broken Access Control Manifests in Loopback

Broken Access Control in Loopback applications typically occurs through several Loopback-specific patterns. The most common is improper use of remotes.beforeRemote and remotes.afterRemote hooks where authorization checks are either missing or incorrectly implemented.

// Vulnerable pattern - missing authorization check
MyModel.beforeRemote('*', async (ctx, unused, next) => {
  // No check if user is authenticated or has permissions
  next();
});

Another frequent issue is the misuse of Loopback's accessType property. When developers set accessType: 'READ' on methods that should be restricted, any authenticated user can access sensitive data.

// Vulnerable - READ access allows anyone to view all user data
module.exports = function(User) {
  User.remoteMethod('find', {
    accessType: 'READ', // Should be 'WRITE' or require specific roles
    returns: {arg: 'users', type: 'array'}
  });
};

Loopback's dynamic scoping can also introduce BOLA (Broken Object Level Authorization) vulnerabilities. When using findById without proper ownership checks, users can access any record by ID.

// Vulnerable - no ownership verification
module.exports = function(Order) {
  Order.findById = async function(id, options) {
    return Order.findById(id); // Any user can access any order
  };
};

The framework's default allowedRoles: $everyone setting on remote methods is another common pitfall. Developers often forget to restrict this, allowing unauthenticated access to sensitive operations.

Loopback-Specific Detection

Detecting Broken Access Control in Loopback requires examining both the codebase and runtime behavior. Start by reviewing all remotes.beforeRemote hooks for missing authorization logic.

# Search for vulnerable patterns
grep -r "beforeRemote" . | grep -v "authorize" | grep -v "role"

Check for exposed methods with overly permissive accessType settings. Any method that returns sensitive data should require specific roles or ownership verification.

// Scan for vulnerable accessType declarations
const vulnerableMethods = [];
for (const model of Object.values(app.models)) {
  for (const method of Object.values(model.settings.remotes)) {
    if (method.accessType === 'READ' && !method.allowedRoles.includes('admin')) {
      vulnerableMethods.push(`${model.modelName}.${method.name}`);
    }
  }
}

middleBrick's black-box scanning approach is particularly effective for Loopback applications. It tests unauthenticated endpoints and verifies that protected routes actually require authentication.

# Scan Loopback API with middleBrick
middlebrick scan https://api.example.com/explorer

The scanner checks for common Loopback patterns like exposed /explorer endpoints, default CRUD operations without proper authorization, and methods that should require admin roles but don't.

For OpenAPI spec analysis, middleBrick resolves Loopback's $ref definitions and cross-references them with runtime findings to identify mismatches between documented security requirements and actual implementation.

Loopback-Specific Remediation

Fixing Broken Access Control in Loopback requires using the framework's built-in authorization features correctly. The most robust approach is implementing Loopback's AccessContext and AccessContextBuilder classes.

const {AccessContext, AccessContextBuilder} = require('@loopback/security');

module.exports = function(Order) {
  Order.beforeRemote('findById', async (ctx, unused, next) => {
    const userId = ctx.req.accessToken.userId;
    const orderId = ctx.args.id;
    
    // Verify ownership
    const order = await Order.findById(orderId);
    if (!order || order.customerId !== userId) {
      const err = new Error('Access denied');
      err.statusCode = 403;
      return next(err);
    }
    
    next();
  });
};

For role-based access control, use Loopback's AuthorizationBuilder to define granular permissions.

const {AuthorizationBuilder} = require('@loopback/authorization');

const authorization = new AuthorizationBuilder()
  .allow(['admin', 'manager'])
  .forResource('Order')
  .forScope('read')
  .build();

module.exports = function(Order) {
  Order.beforeRemote('find', async (ctx, unused, next) => {
    const authContext = new AccessContext({
      principals: [ctx.req.principal],
      resource: 'Order',
      scopes: ['read']
    });
    
    if (!await authorization.authorize(authContext)) {
      const err = new Error('Insufficient permissions');
      err.statusCode = 403;
      return next(err);
    }
    
    next();
  });
};

Implement proper accessType restrictions on all remote methods:

module.exports = function(User) {
  User.remoteMethod('find', {
    accessType: 'READ',
    allowedRoles: ['admin'], // Restrict to admin only
    returns: {arg: 'users', type: 'array'}
  });
};

For dynamic scoping vulnerabilities, always verify resource ownership before returning data:

module.exports = function(Document) {
  Document.beforeRemote('find', async (ctx, unused, next) => {
    const userId = ctx.req.accessToken.userId;
    ctx.args.filter = ctx.args.filter || {};
    ctx.args.filter.where = ctx.args.filter.where || {};
    ctx.args.filter.where.ownerId = userId;
    next();
  });
};

Frequently Asked Questions

How does middleBrick detect Broken Access Control in Loopback APIs?
middleBrick tests unauthenticated access to protected endpoints and verifies that sensitive operations require proper authentication. It checks for exposed Loopback explorer endpoints, default CRUD operations without authorization, and methods that should require specific roles but don't. The scanner also analyzes OpenAPI specs to identify security configuration mismatches.
Can middleBrick scan Loopback APIs with authentication?
Yes, middleBrick can scan authenticated endpoints. You can provide authentication tokens or credentials when submitting a scan. The tool tests both authenticated and unauthenticated paths to identify broken access control vulnerabilities across the entire API surface.