Insecure Deserialization in Adonisjs
How Insecure Deserialization Manifests in Adonisjs
Insecure deserialization in Adonisjs typically occurs when untrusted data is deserialized without proper validation, allowing attackers to execute arbitrary code or manipulate application logic. Adonisjs applications often serialize data using JSON, MessagePack, or custom formats, creating multiple attack surfaces.
The most common Adonisjs-specific scenario involves session management. Adonisjs uses the Adonis/Addons/Session package to store session data, which can be serialized using different drivers (cookie, Redis, database). When using cookie-based sessions, data is often signed but not encrypted, making it vulnerable if an attacker can tamper with the serialized payload.
Consider this vulnerable Adonisjs controller pattern:
class UserController {
async updateProfile({ request, session }) {
const userData = session.get('user_profile');
const updates = request.post();
// Directly merging untrusted data
Object.assign(userData, updates);
session.put('user_profile', userData);
return userData;
}
}Here, an attacker could manipulate the serialized session data to inject malicious objects. If the application later deserializes this data, arbitrary code execution becomes possible.
Another Adonisjs-specific vulnerability appears in middleware that handles serialized request data:
class AuthMiddleware {
async handle({ request }, next) {
const token = request.header('X-Auth-Token');
const userData = await this.decryptToken(token);
// Vulnerable: no validation of deserialized data
request.auth.user = userData;
await next();
}
}Attackers can craft serialized payloads that, when deserialized, execute code during the object reconstruction phase. This is particularly dangerous if the application uses eval(), new Function(), or other dynamic code execution patterns during deserialization.
Adonisjs's Lucid ORM can also be exploited through insecure deserialization when handling complex model relationships:
class PostController {
async show({ params }) {
const post = await Post.find(params.id);
const comments = await post.related('comments').query();
// Vulnerable: directly serializing and deserializing ORM objects
const serialized = JSON.stringify(comments);
const deserialized = JSON.parse(serialized);
return deserialized;
}
}While JSON serialization itself is generally safe, combining it with other deserialization mechanisms or using custom revivers can introduce vulnerabilities.
Adonisjs-Specific Detection
Detecting insecure deserialization in Adonisjs requires examining both code patterns and runtime behavior. Start by auditing your codebase for serialization-related operations:
npm run dev -- --inspectThen use Chrome DevTools to set breakpoints on JSON.parse(), eval(), and any custom deserialization functions. Look for patterns where:
- Session data is deserialized without validation
- Request headers or bodies are directly deserialized
- Database query results are manipulated before deserialization
- Custom serialization formats are used without strict validation
middleBrick's API security scanner specifically detects deserialization vulnerabilities in Adonisjs applications by:
- Analyzing OpenAPI specs for endpoints that accept serialized data
- Testing session management implementations for tampering vulnerabilities
- Scanning for unsafe deserialization patterns in middleware
- Checking for vulnerable configurations in session drivers
To test manually, use tools like Burp Suite or OWASP ZAP to intercept requests and modify serialized data:
const maliciousData = {
__proto__: {
exec: () => {
console.log('Arbitrary code executed!');
}
}
};Send this payload through your Adonisjs endpoints and monitor for unexpected behavior. middleBrick automates this testing by injecting various serialized payloads and monitoring application responses.
Also check your config/session.js for vulnerable configurations:
module.exports = {
driver: 'cookie',
secret: Env.get('APP_KEY'),
// Vulnerable: no encryption, only signing
httpOnly: true,
sameSite: true,
secure: true
}The cookie driver without encryption is particularly risky if session data contains sensitive information or if the application logic trusts deserialized session data.
Adonisjs-Specific Remediation
Remediating insecure deserialization in Adonisjs requires a defense-in-depth approach. Start with the most critical fixes:
1. Use Encrypted Session Storage
Configure Adonisjs to use encrypted session storage instead of signed-only:
// config/session.js
module.exports = {
driver: 'redis', // or 'database'
secret: Env.get('APP_KEY'),
encrypt: true, // Enable encryption
httpOnly: true,
sameSite: true,
secure: true
}2. Validate Serialized Data
Always validate deserialized data against strict schemas:
const { validate } = use('Validator');
class UserController {
async updateProfile({ request, session }) {
const userData = session.get('user_profile');
// Validate before using
const validation = await validate(userData, {
id: 'required|number',
email: 'required|email',
role: 'in:user,admin,moderator'
});
if (validation.fails()) {
return response.status(400).send('Invalid session data');
}
return userData;
}
}3. Use Safe Serialization Libraries
Replace vulnerable serialization with safe alternatives:
const { safeStringify, safeParse } = require('safe-json-parse');
// Instead of JSON.parse() directly
const data = safeParse(serializedData, (key, value) => {
if (typeof value === 'object' && value !== null) {
// Reject dangerous prototypes
if (value.__proto__ || value.constructor !== Object) {
throw new Error('Unsafe object detected');
}
}
return value;
});4. Implement Content Security Policy
Add CSP headers to prevent script execution from untrusted sources:
class SecurityMiddleware {
async handle({ response }, next) {
response.header('Content-Security-Policy', "default-src 'self'; script-src 'self'");
await next();
}
}5. Use middleBrick for Continuous Monitoring
Integrate middleBrick into your development workflow to catch deserialization issues early:
// package.json scripts
"scripts": {
"security:scan": "middlebrick scan https://your-api.com"
}Run this before deployments and in your CI/CD pipeline:
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run middleBrick Scan
run: |
npx middlebrick scan https://staging.your-api.com
continue-on-error: true6. Audit Dependencies
Regularly audit your Adonisjs dependencies for known deserialization vulnerabilities:
npm audit
# Check for specific vulnerable packages
npm ls package-with-deserialization-issuesConsider using npm audit fix for automatic updates of minor vulnerabilities.