CWE-770 in APIs
What is CWE-770?
CWE-770, titled Allocation of Resources Without Limits or Throttling, describes a weakness where an application fails to properly control the allocation of system resources. This can allow an attacker to consume excessive amounts of memory, CPU, file handles, database connections, or other resources, potentially leading to denial of service or other system instability.
The core issue is the absence of enforcement mechanisms that would normally prevent resource exhaustion. When an application doesn't impose limits on resource consumption, a single user or process can monopolize system resources, starving legitimate users and potentially crashing the entire system.
Common manifestations include:
- Unbounded memory allocation (e.g., storing unlimited results in memory)
- Unlimited file uploads without size restrictions
- Unrestricted database query results
- Infinite loops or recursive calls without depth limits
- Unlimited concurrent connections or requests
The weakness is particularly dangerous in shared environments like cloud applications, where resource exhaustion by one tenant can affect others.
CWE-770 in API Contexts
APIs are particularly vulnerable to resource exhaustion attacks due to their stateless nature and the potential for automation. Attackers can easily script thousands of requests per minute, making APIs prime targets for CWE-770 exploitation.
Common API-specific scenarios include:
- Unbounded pagination: APIs that allow clients to request massive datasets without limits. For example,
GET /users?limit=999999999could return millions of records, exhausting server memory. - Unlimited file uploads: APIs accepting file uploads without size restrictions can be exploited to upload multi-gigabyte files, consuming disk space and memory.
- Open-ended search queries: Search APIs without result limits or timeout controls can return enormous result sets.
- Unrestricted concurrent requests: APIs without rate limiting or connection pooling controls can be overwhelmed by parallel requests.
- Memory leaks in streaming APIs: APIs that stream data without proper backpressure handling can accumulate unprocessed data in memory.
Consider this vulnerable Node.js endpoint:
app.get('/api/reports', async (req, res) => {
const reports = await db.query('SELECT * FROM reports');
res.json(reports);
});This endpoint has no pagination, timeout, or result limits. A malicious user could trigger this endpoint repeatedly, causing the database to return millions of rows and exhausting server memory.
Detection
Detecting CWE-770 requires both static code analysis and dynamic testing. Here are the key approaches:
Static Analysis
Review code for missing resource limits:
- Search for database queries without LIMIT clauses
- Look for file upload handlers without size validation
- Check for memory allocation without size checks
- Identify loops and recursive functions without iteration limits
Dynamic Testing
Security scanners like middleBrick can automatically detect resource exhaustion vulnerabilities by:
- Testing API endpoints with large input parameters
- Monitoring response times and resource usage
- Checking for missing rate limiting headers
- Analyzing OpenAPI specs for missing pagination parameters
middleBrick specifically tests for CWE-770 through its Rate Limiting and Input Validation checks. The scanner attempts to trigger resource exhaustion scenarios and reports findings with severity levels and remediation guidance.
Here's an example of what middleBrick might detect:
{
"severity": "high",
"category": "Rate Limiting",
"finding": "API endpoint /api/reports allows unlimited result sets without pagination",
"remediation": "Implement pagination with max limit of 100 items per request"
}The scanner also checks for proper Content-Length headers on file uploads and validates that streaming endpoints implement backpressure mechanisms.
Remediation
Fixing CWE-770 requires implementing proper resource limits throughout your API. Here are specific remediation strategies with code examples:
1. Implement Pagination
Always limit result set sizes:
app.get('/api/reports', async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = Math.min(parseInt(req.query.limit) || 10, 100); // max 100 items
const offset = (page - 1) * limit;
const reports = await db.query(
'SELECT * FROM reports LIMIT $1 OFFSET $2',
[limit, offset]
);
res.json({
data: reports,
pagination: {
page,
limit,
total: await db.query('SELECT COUNT(*) FROM reports')
}
});
});2. File Upload Limits
Enforce maximum file sizes:
const multer = require('multer');
const upload = multer({
limits: {
fileSize: 5 * 1024 * 1024 // 5MB max
}
});
app.post('/api/upload', upload.single('file'), (req, res) => {
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
res.json({ message: 'Upload successful', filename: req.file.filename });
});3. Rate Limiting
Prevent excessive requests:
const rateLimit = require('express-rate-limit');
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP'
});
app.use('/api/', apiLimiter);4. Memory Limits
Prevent unbounded memory allocation:
app.get('/api/stream', async (req, res) => {
const stream = db.queryStream('SELECT * FROM large_table');
// Process stream in chunks to prevent memory exhaustion
const chunkSize = 1000;
let chunk = [];
stream.on('data', (row) => {
chunk.push(row);
if (chunk.length >= chunkSize) {
res.write(JSON.stringify(chunk));
chunk = [];
}
});
stream.on('end', () => {
if (chunk.length > 0) {
res.write(JSON.stringify(chunk));
}
res.end();
});
});5. Timeout Controls
Implement request timeouts:
app.get('/api/slow-operation', async (req, res) => {
const timeout = setTimeout(() => {
return res.status(503).json({ error: 'Request timeout' });
}, 30000); // 30 second timeout
try {
const result = await slowOperation();
clearTimeout(timeout);
res.json(result);
} catch (error) {
clearTimeout(timeout);
res.status(500).json({ error: error.message });
}
});Using middleBrick's CLI, you can verify these fixes:
middlebrick scan https://api.example.com/reports --check rate-limiting,input-validationThe middleBrick GitHub Action can automatically scan your API endpoints in CI/CD pipelines:
- name: Run middleBrick Security Scan
uses: middlebrick/middlebrick-action@v1
with:
url: https://api.example.com
fail-on-severity: high