HIGH request smugglingadonisjs

Request Smuggling in Adonisjs

How Request Smuggling Manifests in Adonisjs

Request smuggling in Adonisjs applications typically occurs when the framework misinterprets the boundaries between HTTP requests, allowing an attacker to hide malicious payloads within seemingly valid requests. This vulnerability is particularly dangerous in Adonisjs because of its flexible middleware system and body parsing capabilities.

The most common manifestation involves manipulating Content-Length and Transfer-Encoding headers. Consider this vulnerable Adonisjs route:

Route.post('/api/users', async ({ request, response }) => {
  const userData = await request.body()
  const user = await User.create(userData)
  return response.json({ success: true, user })
})

An attacker could exploit this by sending:

POST /api/users HTTP/1.1
Host: example.com
Content-Length: 25
Content-Type: application/json
Transfer-Encoding: chunked

0

POST /api/admin HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 23

{"role":"admin"}

In this scenario, the server might process the first chunk as a legitimate request, then interpret the remaining bytes as a second request. The second POST to /api/admin could execute with elevated privileges if the attacker manages to smuggle it to another user's session.

Adonisjs's body parser can also be vulnerable when handling multipart/form-data. The framework uses formidable under the hood, which may not properly validate boundary markers. An attacker could craft a request with overlapping boundaries:

POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
Content-Length: 1234

------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

<malicious content>
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="extra"

extra data
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="test2.txt"
Content-Type: text/plain

<more malicious content>
------WebKitFormBoundaryABC123--

The second file field could overwrite the first or cause the parser to misinterpret subsequent requests.

Another Adonisjs-specific vector involves the framework's support for streaming responses. If an endpoint streams data without proper content-length validation, an attacker could manipulate the stream to include additional request data:

Route.get('/stream', async ({ response }) => {
  const stream = fs.createReadStream('large-file.txt')
  response.implicitEnd = false
  stream.pipe(response)
})

An attacker could send a request with additional data after the Content-Length, which might be interpreted as part of the next request by a vulnerable server.

Adonisjs-Specific Detection

Detecting request smuggling in Adonisjs requires a combination of static analysis and runtime testing. The framework's flexible routing system and middleware chain make certain patterns particularly vulnerable.

Start by examining your route definitions for endpoints that accept raw body data without validation. Use middleBrick's CLI to scan your API endpoints:

npx middlebrick scan https://your-adonisjs-app.com/api/users

middleBrick specifically tests for request smuggling by sending malformed requests with conflicting Content-Length and Transfer-Encoding headers. It also probes for boundary manipulation in multipart requests.

Look for these vulnerable patterns in your Adonisjs codebase:

// Vulnerable: no content length validation
Route.post('/upload', async ({ request }) => {
  const file = await request.file('file')
  // No validation of file boundaries
})

// Vulnerable: streaming without size limits
Route.get('/download', async ({ response }) => {
  const stream = fs.createReadStream('data.zip')
  stream.pipe(response)
})

// Vulnerable: accepting arbitrary JSON without schema
Route.post('/data', async ({ request }) => {
  const payload = await request.body()
  // No validation of payload structure
})

middleBrick's scanner will identify these issues by attempting to smuggle requests through your endpoints and checking if the server processes them incorrectly. The scanner tests 12 security categories including authentication bypass attempts and data exposure that often accompany request smuggling vulnerabilities.

For comprehensive detection, examine your Adonisjs middleware stack. Request smuggling can be introduced by custom middleware that modifies request headers or body without proper validation:

// Vulnerable middleware
export class RequestModifier {
  async handle({ request }, next) {
    const body = await request.body()
    // Maliciously modify body without validation
    request.body = () => ({ ...body, extra: 'data' })
    await next()
  }
}

middleBrick's continuous monitoring (available in Pro plan) can alert you when new endpoints are deployed that might introduce smuggling vulnerabilities, ensuring your API surface remains secure as your application evolves.

Adonisjs-Specific Remediation

Remediating request smuggling in Adonisjs requires a defense-in-depth approach. Start by implementing strict request validation at the framework level.

First, configure Adonisjs to reject ambiguous requests by setting strict content length validation:

// config/bodyparser.js
module.exports = {
  json: {
    limit: '10mb',
    strict: true, // Reject invalid JSON
  },
  multipart: {
    autoProcess: true,
    maxFileSize: '5mb',
    maxFieldSize: '2kb',
  },
  urlencoded: {
    limit: '2mb',
    strict: true,
  },
}

Next, implement request boundary validation in your routes. Adonisjs's validator makes this straightforward:

import { schema } from '@adonisjs/core/validator'

const userSchema = schema.create({
  name: schema.string({}, [rules.minLength(1)]),
  email: schema.string({}, [
    rules.email(),
    rules.maxLength(255)
  ]),
  role: schema.enum(['user', 'admin'], {
    exact: true,
    optional: true
  })
})

Route.post('/api/users', async ({ request, response }) => {
  const payload = await request.validate({
    schema: userSchema,
    messages: {
      'role.enum': 'Invalid role value'
    }
  })
  
  // Safe to process validated payload
  const user = await User.create(payload)
  return response.json({ success: true, user })
})

For file uploads, implement strict boundary validation and size limits:

Route.post('/upload', async ({ request, response }) => {
  const profilePic = request.file('profile_pic', {
    size: '2mb',
    extnames: ['jpg', 'png', 'gif']
  })

  if (!profilePic) {
    return response.badRequest({ error: 'Profile picture required' })
  }

  await profilePic.move(Application.tmpPath('uploads'), {
    name: `${new Date().getTime()}-${profilePic.clientName}`
  })

  if (!profilePic.moved()) {
    return response.badRequest({ error: profilePic.errors })
  }

  return response.json({ success: true, path: profilePic.fileName })
})

Implement request smuggling detection middleware that validates header consistency:

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

export class RequestValidatorMiddleware {
  async handle({ request, response }: HttpContextContract, next: () => Promise) {
    const contentLength = request.headers['content-length']
    const transferEncoding = request.headers['transfer-encoding']

    // Reject requests with both Content-Length and Transfer-Encoding
    if (contentLength && transferEncoding) {
      return response.badRequest({
        error: 'Ambiguous request: cannot have both Content-Length and Transfer-Encoding'
      })
    }

    // Validate Content-Length is a valid number
    if (contentLength) {
      const length = parseInt(contentLength)
      if (isNaN(length) || length < 0) {
        return response.badRequest({
          error: 'Invalid Content-Length header'
        })
      }
    }

    await next()
  }
}

Register this middleware globally in your start/kernel.js:

const globalMiddleware = [
  // ... other middleware
  'App/Middleware/RequestValidatorMiddleware'
]

For streaming endpoints, implement strict content length validation and chunked transfer encoding support:

Route.get('/stream', async ({ request, response }) => {
  const contentLength = request.headers['content-length']
  if (contentLength) {
    const length = parseInt(contentLength)
    if (isNaN(length) || length > 100 * 1024 * 1024) { // 100MB max
      return response.badRequest({
        error: 'Content length exceeds maximum allowed size'
      })
    }
  }

  const stream = fs.createReadStream('data.zip', { highWaterMark: 16 * 1024 })
  response.header('Content-Length', (await fs.stat('data.zip')).size.toString())
  
  stream.on('error', (err) => {
    response.internalServerError({ error: 'Stream error' })
  })

  stream.pipe(response)
})

Finally, integrate middleBrick's GitHub Action into your CI/CD pipeline to automatically scan new endpoints before deployment:

name: Security Scan
on: [pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Run middleBrick Scan
      uses: middlebrick/middlebrick-action@v1
      with:
        target: ${{ secrets.API_URL }}
        token: ${{ secrets.MIDDLEBRICK_TOKEN }}
        fail-on-severity: high
    - name: Fail on security issues
      if: failure()
      run: echo "Security scan failed - please fix issues before merging"

This comprehensive approach ensures your Adonisjs application is protected against request smuggling attacks while maintaining functionality for legitimate users.

Frequently Asked Questions

How does request smuggling differ from HTTP request smuggling?
Request smuggling is the general concept of manipulating how servers interpret HTTP request boundaries, while HTTP request smuggling specifically refers to the technique of sending ambiguous requests that cause servers to misinterpret where one request ends and another begins. In Adonisjs applications, both terms apply to the same vulnerability class, though HTTP request smuggling is the more technically precise term.
Can middleBrick detect request smuggling in Adonisjs applications?
Yes, middleBrick's black-box scanner specifically tests for request smuggling vulnerabilities by sending malformed requests with conflicting headers and boundary manipulations. It attempts to smuggle requests through your Adonisjs endpoints and analyzes whether the server processes them incorrectly, providing detailed findings with severity levels and remediation guidance.