Insufficient Resource Pool
Description
Insufficient Resource Pool is a vulnerability that occurs when a system's resource pool cannot meet peak demand, allowing attackers to exhaust available resources by making a large number of requests, thereby blocking legitimate users. The resource pool (such as database connections, threads, file handles, or sockets) is undersized for the expected load or lacks protection against deliberate exhaustion. Frequently the consequence is a "flood" of connections or sessions that prevents the system from serving legitimate users.
Risk
Insufficient resource pools enable denial of service attacks where attackers consume all available resources. Database connection pool exhaustion prevents applications from processing queries. Thread pool exhaustion causes request timeouts and application hangs. File handle exhaustion can crash applications or operating systems. Socket exhaustion prevents new network connections. These attacks are particularly effective when resources are allocated to unauthenticated users or when there are no limits per client. The attacks can be performed with minimal attacker resources while causing significant service disruption.
Solution
Avoid resource-intensive operations for unauthenticated or invalid requests. Implement velocity checks to detect and block abusive behavior. Apply rate limiting per client/IP address. Use load balancing to distribute traffic. Properly close resource handles when no longer needed. Set appropriate timeouts on resource acquisition. Implement connection limits per user or source. Protect resource-intensive operations with authentication and authorization. Monitor resource pool utilization and alert on anomalies. Size pools appropriately for expected peak load with safety margin.
Common Consequences
| Impact | Details |
|---|---|
| Availability | Scope: Availability Denial of Service - crash, exit, restart, or other availability issues. Resource floods often trigger crashes beyond just resource denial, potentially representing additional vulnerabilities. |
| Integrity | Scope: Integrity Unexpected state changes may occur when systems are under resource pressure. |
Example Code
Vulnerable Code
// Vulnerable: Small connection pool easily exhausted
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class VulnerableConnectionPool {
public DataSource createDataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/mydb");
ds.setUsername("user");
ds.setPassword("password");
// Vulnerable: Only 5 connections - easily exhausted
ds.setMaxTotal(5);
ds.setMaxIdle(5);
// Vulnerable: Long wait time - requests queue up
ds.setMaxWaitMillis(60000);
return ds;
}
}
// Vulnerable: No connection release
public class VulnerableService {
public void processRequest(DataSource ds) throws SQLException {
Connection conn = ds.getConnection(); // Gets connection
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// Process results...
// Vulnerable: Connection never closed!
// Pool exhaustion over time
}
}
# Vulnerable: Fixed thread pool easily exhausted
from concurrent.futures import ThreadPoolExecutor
import time
# Vulnerable: Only 4 threads available
executor = ThreadPoolExecutor(max_workers=4)
def vulnerable_handle_request(request):
# Vulnerable: Long-running operation blocks thread
# Attacker can tie up all threads with slow requests
time.sleep(30) # Simulates slow operation
return process(request)
def vulnerable_server():
while True:
request = accept_connection()
# Vulnerable: No limit on pending requests
# Vulnerable: No timeout for slow clients
executor.submit(vulnerable_handle_request, request)
// Vulnerable: File descriptor limit not checked
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int vulnerable_server(int listen_fd) {
while (1) {
// Vulnerable: No check on number of open connections
int client_fd = accept(listen_fd, NULL, NULL);
if (client_fd >= 0) {
// Vulnerable: Keeps connection open
// No limit on simultaneous connections
handle_client(client_fd);
// Vulnerable: Never closes client_fd
}
}
return 0;
}
Fixed Code
// Fixed: Properly sized pool with protection
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class SecureConnectionPool {
public DataSource createDataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/mydb");
ds.setUsername("user");
ds.setPassword("password");
// Fixed: Appropriately sized pool
ds.setMaxTotal(50); // Reasonable max connections
ds.setMaxIdle(20); // Keep some idle connections
ds.setMinIdle(5); // Minimum idle connections
// Fixed: Short wait with timeout
ds.setMaxWaitMillis(5000); // 5 second timeout
// Fixed: Validation and eviction
ds.setTestOnBorrow(true);
ds.setValidationQuery("SELECT 1");
ds.setTimeBetweenEvictionRunsMillis(30000);
ds.setMinEvictableIdleTimeMillis(60000);
// Fixed: Remove abandoned connections
ds.setRemoveAbandonedOnBorrow(true);
ds.setRemoveAbandonedTimeout(60); // 60 seconds
return ds;
}
}
// Fixed: Always close connections
public class SecureService {
public void processRequest(DataSource ds) throws SQLException {
// Fixed: Try-with-resources ensures closure
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
// Process results...
} // Connection automatically closed
}
}
# Fixed: Bounded queue and per-client limits
from concurrent.futures import ThreadPoolExecutor
import time
from collections import defaultdict
import threading
# Fixed: Reasonable pool size with bounded queue
executor = ThreadPoolExecutor(max_workers=50)
# Fixed: Track per-client connections
client_requests = defaultdict(int)
client_lock = threading.Lock()
MAX_PER_CLIENT = 5
def secure_handle_request(client_id, request):
try:
# Fixed: Timeout for operations
with timeout(10): # 10 second max
return process(request)
finally:
# Fixed: Decrement counter when done
with client_lock:
client_requests[client_id] -= 1
def secure_server():
while True:
request, client_id = accept_connection()
# Fixed: Per-client rate limiting
with client_lock:
if client_requests[client_id] >= MAX_PER_CLIENT:
reject_connection(request, "Too many concurrent requests")
continue
client_requests[client_id] += 1
try:
# Fixed: Use submit with bounded queue
future = executor.submit(secure_handle_request, client_id, request)
# Queue is bounded by executor's internal limit
except Exception:
with client_lock:
client_requests[client_id] -= 1
reject_connection(request, "Server overloaded")
// Fixed: Track and limit connections
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define MAX_CONNECTIONS 100
static int active_connections = 0;
static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
int secure_server(int listen_fd) {
while (1) {
int client_fd = accept(listen_fd, NULL, NULL);
if (client_fd < 0) {
continue;
}
// Fixed: Check connection limit
pthread_mutex_lock(&conn_mutex);
if (active_connections >= MAX_CONNECTIONS) {
pthread_mutex_unlock(&conn_mutex);
// Fixed: Reject excess connections
const char *msg = "Server busy\n";
write(client_fd, msg, strlen(msg));
close(client_fd);
continue;
}
active_connections++;
pthread_mutex_unlock(&conn_mutex);
// Fixed: Handle in thread with cleanup
pthread_t thread;
int *fd_ptr = malloc(sizeof(int));
*fd_ptr = client_fd;
pthread_create(&thread, NULL, handle_client_thread, fd_ptr);
pthread_detach(thread);
}
return 0;
}
void *handle_client_thread(void *arg) {
int client_fd = *(int *)arg;
free(arg);
// Set socket timeout
struct timeval tv = {.tv_sec = 30, .tv_usec = 0};
setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
// Handle client...
handle_client(client_fd);
// Fixed: Always close and decrement
close(client_fd);
pthread_mutex_lock(&conn_mutex);
active_connections--;
pthread_mutex_unlock(&conn_mutex);
return NULL;
}
CVE Examples
- CVE-1999-1363 — File lock exhaustion causing crash.
- CVE-2001-1340 — Single connection without forced disconnection of unauthenticated users.
- CVE-2002-0406 — Connection exhaustion via unauthenticated requests.
References
- MITRE Corporation. "CWE-410: Insufficient Resource Pool." https://cwe.mitre.org/data/definitions/410.html
- OWASP. "Denial of Service Cheat Sheet." https://cheatsheetseries.owasp.org/