Uncontrolled Resource Consumption occurs when an application fails to limit how much of a shared resource—such as memory, CPU time, disk space, or network…
Uncontrolled Resource Consumption occurs when an application fails to limit how much of a shared resource—such as memory, CPU time, disk space, or network connections—a single user or request can consume. An attacker can exploit this by making requests that exhaust the resource, causing the application to become slow, unresponsive, or crash entirely, denying service to legitimate users.
02How It Happens
This weakness typically arises when an application processes user input without enforcing limits on the work performed or resources allocated. Common patterns include accepting unbounded file uploads, processing arbitrarily large data structures, running loops controlled by user input without iteration caps, or opening connections without connection pooling or timeouts. The flaw is often invisible during normal use because legitimate users rarely trigger the limits, but a determined attacker can craft requests designed to consume resources at scale.
03Real-World Impact
Resource exhaustion attacks can render a web application unavailable to all users, even if the attacker has no ability to steal data or modify content. A single malicious request might consume all available memory, fill the disk, or exhaust the database connection pool, forcing administrators to manually restart services. In shared hosting environments, resource exhaustion in one application can degrade performance for neighboring applications. Recovery often requires manual intervention and can result in lost revenue, damaged reputation, and incident response costs.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import sqlite3
def process_user_data(user_input):
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
# No limit on how many rows are fetched
cursor.execute("SELECT * FROM large_table WHERE id IN (?)", (user_input,))
results = cursor.fetchall()
# Process all results without bounds
processed = [expensive_operation(row) for row in results]
return processed
Why it's vulnerable: The function fetches and processes an unbounded number of rows based on user input, with no limit on memory or CPU time. An attacker can supply input that matches millions of rows, exhausting memory and CPU.
Fixed pattern
import sqlite3
def process_user_data(user_input, max_rows=100):
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
# Limit the number of rows fetched
cursor.execute("SELECT * FROM large_table WHERE id IN (?) LIMIT ?",
(user_input, max_rows))
results = cursor.fetchall()
# Process only the limited result set
processed = [expensive_operation(row) for row in results]
return processed
Vulnerable pattern
<?php
// No limit on file upload size or processing
if ($_FILES['upload']['size'] > 0) {
$file_content = file_get_contents($_FILES['upload']['tmp_name']);
// Process entire file without bounds
$lines = explode("\n", $file_content);
foreach ($lines as $line) {
expensive_database_operation($line);
}
}
?>
Why it's vulnerable: The script processes an entire uploaded file line-by-line without checking file size or limiting iterations. An attacker can upload a multi-gigabyte file or one with millions of lines, exhausting memory and CPU.
Set explicit limits on file uploads — enforce maximum file size at the application and web server level (e.g., php.iniupload_max_filesize, nginx client_max_body_size).
Implement pagination and result limits — cap the number of database rows, API results, or list items returned per request; use LIMIT clauses and offset-based pagination.
Add timeouts to long-running operations — set execution time limits on scripts, database queries, and external API calls; use set_time_limit() in PHP or task timeouts in background job queues.
Use connection pooling and limits — restrict the number of simultaneous database connections, file handles, and network sockets; close idle connections promptly.
Validate input size and complexity — reject requests with excessively large JSON payloads, XML documents, or query strings before processing; use Content-Length headers to pre-check size.
Monitor resource usage — log and alert on unusual spikes in memory, CPU, or disk I/O; set up automated scaling or circuit breakers to shed load under stress.
06Signs You May Already Be Affected
Watch for unexplained application slowdowns, out-of-memory errors, or frequent service restarts that correlate with specific user actions or request patterns. Check application and system logs for requests with unusually large payloads, long execution times, or repeated failures; also review disk usage for unexpected growth in temporary or cache directories. If you notice the application becomes unresponsive after processing a single request or file upload, resource exhaustion may be the cause.