CWE-789 describes code that allocates memory based on an untrusted, large size value without checking that the size is within expected limits. An attacker can then ask for an arbitrary amount of memory.
It affects C and C++ and also higher-level languages, since the problem is the missing limit and not the language.
How it happens
A length field arrives in a request, a file header or an API parameter. The code trusts it and allocates.
The MITRE record shows several forms:
- CVE-2023-2253: a query capability for an API endpoint allowed a large value for the number of records to return, leading to allocation of a large array.
- CVE-2019-19911: a chain where a Python library did not limit the resources used to process images that specify a very large number of bands, leading to excessive memory consumption.
- CVE-2010-3701: a program used alloca for encoding messages, and large messages caused a segmentation fault.
@app.get("/items")
def items():
n = int(request.args["count"])
return jsonify([make_item() for _ in range(n)]) # count=999999999
What an attacker gains
The record lists denial of service through memory consumption. Not controlling allocation can request too much system memory and crash the product or the host. One cheap request can cost you a worker process.
How to find it
MITRE names fuzzing, static analysis and dynamic analysis with runtime checks. Add:
- Review every allocation whose size comes from input.
- Send huge values in size, count, page and length parameters on a test instance and watch memory.
- Fuzz file parsers with headers that claim enormous dimensions.
How to fix it
Set an upper bound and enforce it before allocating.
MAX_COUNT = 1000
n = int(request.args.get("count", 10))
if not 0 < n <= MAX_COUNT:
abort(400)
- Decide the largest legitimate size for each field and reject anything above it.
- Check for integer overflow when multiplying counts by element sizes.
- Avoid stack allocation sized by input.
- Set process memory limits and request body limits as a backstop.
- Allocate as data arrives and not up front from a claimed size.
Quick check
Why not just catch the out-of-memory error?
By then the host may already be starved or the process killed. Validate the size first.