Denial Of Service in Feathersjs
How Denial Of Service Manifests in Feathersjs
Denial of Service (DoS) in Feathersjs applications typically exploits the framework's real-time features and service architecture. The most common vectors target Feathersjs's socket.io-based real-time connections, service hooks that create infinite loops, and database operations that can be triggered at scale.
Real-time connections are particularly vulnerable. Feathersjs maintains persistent WebSocket connections through socket.io, and each connection consumes server resources. An attacker can open thousands of connections simultaneously, exhausting available sockets and memory. The default socket.io configuration allows unlimited connections, making this a critical weakness.
Service hooks present another attack surface. Consider this vulnerable pattern:
app.service('users').hooks({
before: {
create: [
async (context) => {
const users = await context.app.service('users').find();
// Infinite recursion if not careful
return context;
}
]
}
});This hook triggers a find() operation that could recursively invoke hooks, creating an infinite loop that consumes CPU resources.
Database operations in Feathersjs can also be exploited. The framework's flexible query syntax allows complex operations that may not be properly rate-limited. An attacker can send requests with expensive query parameters like $limit: 1000000 or nested $populate operations that join multiple tables, causing database timeouts and connection pool exhaustion.
Batch operations present unique risks. Feathersjs's patch() and remove() methods support bulk operations through query parameters. Without proper validation, an attacker could delete thousands of records with a single request, overwhelming database write capacity and potentially causing cascading failures in related services.
Memory exhaustion attacks target Feathersjs's event handling. The framework emits events for every service operation, and without proper backpressure handling, event listeners can accumulate, holding references to objects and preventing garbage collection. This is especially problematic in applications with complex event chains or recursive event triggers.
Feathersjs-Specific Detection
Detecting DoS vulnerabilities in Feathersjs requires both manual code review and automated scanning. middleBrick's API security scanner includes specific checks for Feathersjs applications, analyzing both the runtime behavior and any OpenAPI specifications.
For runtime scanning, middleBrick tests Feathersjs-specific endpoints by sending requests that trigger common DoS patterns. It attempts to establish multiple WebSocket connections to test connection limits, sends queries with expensive parameters to evaluate database handling, and tests batch operations with large payloads.
The scanner examines service hooks for recursive patterns and infinite loops. It analyzes the hook chain to identify operations that could create circular dependencies or unbounded recursion. For example:
app.service('messages').hooks({
before: {
create: [
async (context) => {
// Vulnerable: could trigger infinite chain
await context.app.service('logs').create({ message: 'created' });
return context;
}
]
}
});middleBrick detects this pattern and flags it as a potential DoS vector.
When analyzing OpenAPI specifications, middleBrick resolves $ref references and validates that rate limiting is properly defined for all endpoints. It checks for missing authentication requirements on endpoints that should be protected and verifies that pagination parameters have reasonable defaults.
The scanner also tests Feathersjs's real-time channels configuration. By default, channels can be too permissive, allowing unauthorized users to subscribe to events. middleBrick attempts to subscribe to protected channels and verifies that authentication is properly enforced.
For applications using Feathersjs's authentication system, middleBrick tests for missing rate limiting on authentication endpoints. Without proper limits, these endpoints become prime targets for credential stuffing attacks that can also serve as DoS vectors by consuming authentication resources.
Feathersjs-Specific Remediation
Securing Feathersjs applications against DoS attacks requires a multi-layered approach using the framework's built-in features and Node.js best practices. The most effective strategy combines rate limiting, connection management, and query validation.
For WebSocket connections, configure socket.io with connection limits and timeout settings:
const io = require('socket.io')(server, {
maxHttpBufferSize: 1e6, // 1MB message size limit
pingTimeout: 60000,
pingInterval: 25000,
perMessageDeflate: false,
cors: {
origin: ['https://yourdomain.com'],
methods: ['GET', 'POST']
}
});
io.of('/v1').on('connection', (socket) => {
// Limit connections per IP
const ip = socket.handshake.address;
if (activeConnections[ip] >= 100) {
socket.disconnect();
}
});For service-level protection, implement rate limiting using feathers-rate-limit:
const rateLimit = require('feathers-rate-limit');
app.service('messages').hooks({
before: {
all: [
rateLimit({
window: 60000, // 1 minute
limit: 100, // 100 requests per minute
key: (context) => context.params.user?.id || context.params.ip,
handler: async (context) => {
throw new Error('Rate limit exceeded');
}
})
]
}
});Validate and sanitize all query parameters to prevent expensive database operations:
app.service('users').hooks({
before: {
find: [
async (context) => {
const { $limit, $skip, $populate } = context.params.query || {};
// Enforce reasonable limits
if ($limit > 100) {
context.params.query.$limit = 100;
}
// Prevent excessive population
if ($populate && $populate.length > 3) {
throw new Error('Too many population parameters');
}
return context;
}
]
}
});Implement circuit breakers for external service calls to prevent cascading failures:
const CircuitBreaker = require('opossum');
const breaker = new CircuitBreaker(async (data) => {
return await externalService.create(data);
}, {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
});
app.service('external').hooks({
before: {
create: [
async (context) => {
context.params.breaker = breaker;
return context;
}
]
}
});For batch operations, implement per-operation limits and confirmation requirements:
app.service('records').hooks({
before: {
patch: [
async (context) => {
const { query } = context.params;
// Limit batch size
if (query && query.$limit && query.$limit > 50) {
throw new Error('Batch size limited to 50 records');
}
// Require confirmation for large operations
if (query && query.$limit && query.$limit > 10) {
if (!context.params.query.confirm) {
throw new Error('Large batch operations require confirmation');
}
}
return context;
}
]
}
});Related CWEs: resourceConsumption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-400 | Uncontrolled Resource Consumption | HIGH |
| CWE-770 | Allocation of Resources Without Limits | MEDIUM |
| CWE-799 | Improper Control of Interaction Frequency | MEDIUM |
| CWE-835 | Infinite Loop | HIGH |
| CWE-1050 | Excessive Platform Resource Consumption | MEDIUM |
Frequently Asked Questions
How does middleBrick specifically detect DoS vulnerabilities in Feathersjs applications?
middleBrick performs active scanning of Feathersjs endpoints, testing for connection exhaustion by establishing multiple WebSocket connections simultaneously. It sends requests with expensive query parameters like $limit: 1000000 to evaluate database handling, and tests batch operations with large payloads to identify missing validation. The scanner also analyzes service hooks for recursive patterns that could create infinite loops, and examines OpenAPI specifications for missing rate limiting definitions.
What's the most critical DoS vulnerability specific to Feathersjs's real-time features?
The most critical vulnerability is the lack of connection limits on WebSocket endpoints. Feathersjs's default socket.io configuration allows unlimited connections, enabling attackers to open thousands of simultaneous connections that exhaust server resources. This is compounded by missing authentication on real-time channels, allowing unauthorized users to subscribe to events and consume bandwidth. Implementing connection limits, proper authentication on channels, and timeout configurations is essential for mitigating this risk.