Asymmetric Resource Consumption (Amplification)

Description

Asymmetric Resource Consumption (Amplification) is a vulnerability that occurs when a product does not properly control situations in which an adversary can cause the product to consume or produce excessive resources without requiring the adversary to invest equivalent work or resources. This creates poor performance through non-linear resource amplification, where small attacker inputs cause disproportionately large resource consumption. Common examples include DNS amplification attacks, XML bombs, and algorithmic complexity attacks.

Risk

Asymmetric resource consumption enables highly effective denial of service attacks. Attackers can exhaust server resources (CPU, memory, bandwidth) with minimal investment. In DNS amplification attacks, small queries generate large responses directed at victims. XML entity expansion (billion laughs attack) can expand kilobytes of input into gigabytes of memory. Algorithmic complexity attacks can turn O(n) operations into O(n²) or exponential time. These attacks are particularly dangerous because they require minimal attacker resources while maximizing victim resource consumption, making them economically viable for attackers.

Solution

Allocate resources commensurate with client access levels. Track and meter resource usage appropriately. Implement rate limiting and request throttling. Disable resource-intensive algorithms on servers where feasible. Set strict limits on entity expansion in XML parsers. Use linear-time algorithms where possible. Validate input sizes before processing. Implement timeouts for long-running operations. Consider using proof-of-work mechanisms to balance client and server resource expenditure.

Common Consequences

ImpactDetails
AvailabilityScope: Availability

DoS: Amplification - Resource consumption attacks causing availability impacts. DoS: Resource Consumption - Excessive CPU, memory, or other resources depleted.

Example Code

Vulnerable Code

# Vulnerable: XML bomb (billion laughs attack)
import xml.etree.ElementTree as ET

def vulnerable_parse_xml(xml_string):
    # Vulnerable: No entity expansion limits
    tree = ET.fromstring(xml_string)
    return tree

# Attack payload (billion laughs):
# <?xml version="1.0"?>
# <!DOCTYPE lolz [
#   <!ENTITY lol "lol">
#   <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
#   <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
#   ...more levels...
# ]>
# <lolz>&lol9;</lolz>
# This can expand to gigabytes of memory!
// Vulnerable: Regex with catastrophic backtracking (ReDoS)
public class VulnerableValidator {

    public boolean validateInput(String input) {
        // Vulnerable: Nested quantifiers cause exponential backtracking
        // Input like "aaaaaaaaaaaaaaaaaaaaaaaaaaaaX" can take hours
        return input.matches("^(a+)+$");
    }

    public boolean validateEmail(String email) {
        // Vulnerable: Complex regex with backtracking
        String pattern = "^([a-zA-Z0-9]+\\.?)+@([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,}$";
        return email.matches(pattern);
    }
}
// Vulnerable: Hash table with predictable collision
typedef struct {
    char *key;
    void *value;
    struct node *next;
} HashNode;

unsigned int vulnerable_hash(const char *key) {
    // Vulnerable: Weak hash function
    // Attacker can craft inputs that all hash to same bucket
    unsigned int hash = 0;
    while (*key) {
        hash = hash * 31 + *key++;
    }
    return hash % TABLE_SIZE;
}

void vulnerable_insert(HashTable *table, const char *key, void *value) {
    // Vulnerable: With crafted keys, all items go to same bucket
    // Lookup becomes O(n) instead of O(1)
    unsigned int index = vulnerable_hash(key);
    // Insert at head of chain...
}

Fixed Code

# Fixed: Disable entity expansion in XML parsing
import defusedxml.ElementTree as ET  # Use defusedxml library

def secure_parse_xml(xml_string, max_size=1024*1024):  # 1MB limit
    # Fixed: Check size before parsing
    if len(xml_string) > max_size:
        raise ValueError("XML too large")

    # Fixed: defusedxml prevents entity expansion attacks
    try:
        tree = ET.fromstring(xml_string)
        return tree
    except ET.ParseError as e:
        raise ValueError(f"Invalid XML: {e}")

# Alternative: Configure standard parser with limits
from xml.etree.ElementTree import XMLParser

def secure_parse_xml_standard(xml_string):
    parser = XMLParser()
    # Python 3.9+ supports forbid_dtd and forbid_entities
    # For older versions, use defusedxml
// Fixed: Use atomic groups or possessive quantifiers to prevent backtracking
public class SecureValidator {

    public boolean validateInput(String input) {
        // Fixed: Use possessive quantifier (no backtracking)
        return input.matches("^a++$");
    }

    public boolean validateEmail(String email) {
        // Fixed: Simpler regex without nested quantifiers
        // Also add length limit
        if (email.length() > 254) {
            return false;
        }

        // Fixed: Use atomic groups or simpler pattern
        String pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
        return email.matches(pattern);
    }

    // Alternative: Use timeout for regex matching
    public boolean validateWithTimeout(String input, String pattern) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Boolean> future = executor.submit(() -> input.matches(pattern));

        try {
            return future.get(1, TimeUnit.SECONDS);  // 1 second timeout
        } catch (TimeoutException e) {
            future.cancel(true);
            return false;  // Treat timeout as invalid
        } catch (Exception e) {
            return false;
        } finally {
            executor.shutdown();
        }
    }
}
// Fixed: Use cryptographically strong hash with random seed
#include <stdlib.h>
#include <string.h>

static uint64_t hash_seed;

void init_hash_table() {
    // Fixed: Initialize with random seed at startup
    hash_seed = ((uint64_t)rand() << 32) | rand();
}

unsigned int secure_hash(const char *key) {
    // Fixed: SipHash or similar keyed hash function
    uint64_t hash = hash_seed;
    while (*key) {
        hash = hash * 0x5bd1e995 + *key++;
        hash ^= hash >> 15;
    }
    return (unsigned int)(hash % TABLE_SIZE);
}

// Alternative: Use red-black tree for worst-case O(log n) instead of hash table

CVE Examples

  • CVE-1999-0513 — Smurf amplification attack using ICMP echo requests to broadcast addresses.
  • CVE-2003-1564 — XML bombs using entity expansion to consume gigabytes of memory.
  • CVE-2020-10735 — Python string-to-int conversion with unexpectedly high digit counts causes CPU exhaustion.
  • CVE-2013-5211 — NTP monlist command enables amplification attacks.
  • CVE-2002-20001 — DHE key agreement attacks force expensive cryptographic computations.

References

  1. MITRE Corporation. "CWE-405: Asymmetric Resource Consumption (Amplification)." https://cwe.mitre.org/data/definitions/405.html
  2. OWASP. "XML External Entity Prevention Cheat Sheet." https://cheatsheetseries.owasp.org/