Allocation of Resources Without Limits or Throttling
Description
Allocation of Resources Without Limits or Throttling occurs when a product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated. This allows attackers to consume excessive amounts of resources such as memory, CPU cycles, file handles, network connections, disk space, or database connections. Without proper limits or throttling mechanisms, a single malicious or misbehaving client can exhaust resources and cause denial of service for all users of the system.
Risk
Resource exhaustion attacks are among the most common denial of service vectors. CVE-2025-69228 in aiohttp allows attackers to exhaust server memory through specially crafted HTTP POST requests. CVE-2025-66560 in Quarkus causes worker thread exhaustion when clients drop connections during response transmission, leading to complete service denial. CVE-2025-48976 in Apache Commons FileUpload enables DoS through multipart headers without size limits. CVE-2024-26308 in Apache Commons Compress affects file decompression. These vulnerabilities can bring down entire services, affecting business continuity, and in cloud environments can also lead to significant unexpected costs.
Solution
Implement strict resource limits at all levels. Set maximum sizes for uploads, request bodies, and allocations. Implement rate limiting per user, IP, and globally. Use connection pooling with fixed maximum sizes. Set timeouts on all operations. Implement backpressure mechanisms to slow down when resources are constrained. Monitor resource consumption and alert on anomalies. Use circuit breakers to prevent cascade failures. Design systems to degrade gracefully under load rather than crash. Configure web servers and frameworks with appropriate limits.
Common Consequences
| Impact | Details |
|---|---|
| Availability | Scope: Denial of Service Resource exhaustion prevents legitimate users from accessing the service. |
| Financial | Scope: Cost Amplification In cloud environments, attackers can trigger significant computing and storage costs. |
| System Stability | Scope: Cascade Failures Resource exhaustion in one component can trigger failures in dependent systems. |
Example Code + Solution Code
Vulnerable Code
# VULNERABLE: No limit on upload size
from flask import Flask, request
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload():
# No size limit - attacker can upload gigabytes
file = request.files['file']
file.save(f'/uploads/{file.filename}')
return 'OK'
# VULNERABLE: Unbounded list allocation
@app.route('/process', methods=['POST'])
def process():
data = request.json
# No limit on items array size
items = data.get('items', []) # Could be millions of items
results = [process_item(item) for item in items]
return jsonify(results)
# VULNERABLE: No rate limiting
@app.route('/api/search')
def search():
# Attacker can make unlimited requests
query = request.args.get('q')
return jsonify(expensive_search(query))
// VULNERABLE: Unbounded thread creation
public class RequestHandler {
public void handleRequest(Socket socket) {
// Creates new thread for each request - no limit!
new Thread(() -> processRequest(socket)).start();
}
}
// VULNERABLE: No memory limit on data structures
public class DataCollector {
private List<Record> records = new ArrayList<>();
public void addRecord(Record record) {
// List can grow without bound
records.add(record);
}
}
// VULNERABLE: No limit on file reading
public String readFile(String path) throws IOException {
// Could be a multi-gigabyte file
return new String(Files.readAllBytes(Paths.get(path)));
}
// VULNERABLE: No request body size limit
const express = require('express');
const app = express();
app.use(express.json()); // Default has high limit
app.post('/data', (req, res) => {
// req.body could be enormous
const data = req.body;
processData(data);
res.json({ status: 'ok' });
});
// VULNERABLE: Regex without timeout (ReDoS)
app.get('/validate', (req, res) => {
const email = req.query.email;
// Evil regex with catastrophic backtracking
const valid = /^([a-z]+)+@[a-z]+\.[a-z]+$/.test(email);
res.json({ valid });
});
Fixed Code
# SAFE: Request size limits and rate limiting
from flask import Flask, request, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB max
limiter = Limiter(
app=app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/upload', methods=['POST'])
@limiter.limit("10 per minute")
def upload_safe():
file = request.files.get('file')
if not file:
return 'No file', 400
# Additional size check
file.seek(0, 2) # Seek to end
size = file.tell()
file.seek(0)
if size > app.config['MAX_CONTENT_LENGTH']:
return 'File too large', 413
# Save with secure filename
filename = secure_filename(file.filename)
file.save(f'/uploads/{filename}')
return 'OK'
# SAFE: Bounded list processing
MAX_ITEMS = 1000
@app.route('/process', methods=['POST'])
@limiter.limit("30 per minute")
def process_safe():
data = request.json
if not isinstance(data, dict):
return 'Invalid request', 400
items = data.get('items', [])
if len(items) > MAX_ITEMS:
return f'Too many items (max {MAX_ITEMS})', 400
results = [process_item(item) for item in items]
return jsonify(results)
# SAFE: Rate limited expensive operation
@app.route('/api/search')
@limiter.limit("10 per minute")
def search_safe():
query = request.args.get('q', '')
if len(query) > 100:
return 'Query too long', 400
return jsonify(expensive_search(query))
// SAFE: Thread pool with fixed size
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SecureRequestHandler {
private static final int MAX_THREADS = 100;
private static final int MAX_PENDING = 1000;
private final ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
private final Semaphore semaphore = new Semaphore(MAX_PENDING);
public void handleRequest(Socket socket) throws InterruptedException {
// Limit pending requests
if (!semaphore.tryAcquire(5, TimeUnit.SECONDS)) {
socket.close();
throw new RejectedExecutionException("Too many pending requests");
}
executor.submit(() -> {
try {
processRequest(socket);
} finally {
semaphore.release();
}
});
}
}
// SAFE: Bounded data structure
public class BoundedDataCollector {
private static final int MAX_RECORDS = 10000;
private final List<Record> records = new ArrayList<>();
public synchronized void addRecord(Record record) throws CapacityExceededException {
if (records.size() >= MAX_RECORDS) {
throw new CapacityExceededException("Maximum records reached");
}
records.add(record);
}
}
// SAFE: Streaming file reading with limits
public String readFileSafe(String path, long maxBytes) throws IOException {
Path filePath = Paths.get(path);
long fileSize = Files.size(filePath);
if (fileSize > maxBytes) {
throw new IOException("File too large: " + fileSize + " bytes");
}
// Read with limit
try (InputStream is = Files.newInputStream(filePath);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[8192];
long totalRead = 0;
int read;
while ((read = is.read(buffer)) != -1) {
totalRead += read;
if (totalRead > maxBytes) {
throw new IOException("File exceeded max size during read");
}
bos.write(buffer, 0, read);
}
return bos.toString(StandardCharsets.UTF_8);
}
}
// SAFE: Express with proper limits
const express = require('express');
const rateLimit = require('express-rate-limit');
const slowDown = require('express-slow-down');
const app = express();
// Limit request body size
app.use(express.json({ limit: '100kb' }));
app.use(express.urlencoded({ limit: '100kb', extended: true }));
// Global rate limiter
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per window
message: 'Too many requests, please try again later'
});
// Speed limiter - slows down repeat requests
const speedLimiter = slowDown({
windowMs: 15 * 60 * 1000,
delayAfter: 50,
delayMs: 500
});
app.use(limiter);
app.use(speedLimiter);
app.post('/data', (req, res) => {
const data = req.body;
// Validate data structure
if (!data || typeof data !== 'object') {
return res.status(400).json({ error: 'Invalid data' });
}
// Check array sizes
if (data.items && data.items.length > 100) {
return res.status(400).json({ error: 'Too many items' });
}
processData(data);
res.json({ status: 'ok' });
});
// SAFE: Use safe regex library or validate input length
const validator = require('validator');
app.get('/validate', (req, res) => {
const email = req.query.email || '';
// Limit input length to prevent ReDoS
if (email.length > 254) {
return res.json({ valid: false });
}
// Use well-tested validation library
const valid = validator.isEmail(email);
res.json({ valid });
});
Exploited in the Wild
aiohttp Memory Exhaustion (aiohttp, 2025)
CVE-2025-69228 in aiohttp 3.13.2 and earlier allows attackers to send specially crafted HTTP POST requests that cause unbounded memory allocation, leading to server crashes and denial of service for asynchronous Python web applications.
Quarkus Worker Thread Exhaustion (Quarkus, 2025)
CVE-2025-66560 in Quarkus before 3.31.0 causes worker threads to block indefinitely when client connections drop during HTTP response transmission, leading to thread pool exhaustion and complete service denial.
Apache Commons FileUpload DoS (Apache, 2025)
CVE-2025-48976 in Apache Commons FileUpload 1.0-1.6 and 2.0.0-M1 to 2.0.0-M4 allows denial of service through multipart headers without sufficient size limits.
Tools to test/exploit
-
slowloris — slow HTTP denial of service tool.
-
wrk — HTTP benchmarking and load testing.
-
vegeta — HTTP load testing tool.
CVE Examples
-
CVE-2025-69228 — aiohttp memory exhaustion.
-
CVE-2025-66560 — Quarkus thread exhaustion.
-
CVE-2024-26308 — Apache Commons Compress resource exhaustion.
References
-
MITRE. "CWE-770: Allocation of Resources Without Limits or Throttling." https://cwe.mitre.org/data/definitions/770.html
-
OWASP. "Denial of Service Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html