CVE-2022-48564 - How a Bug in Python’s plistlib.py Let Malicious Plists Eat Your RAM and CPU

The last thing you want is for a simple configuration file to crash your app or kill your server. But that’s exactly what could happen if you're using Python (up to version 3.9.1) and its standard plistlib module to process Apple Property List (plist) files—because of a subtle bug now tracked as CVE-2022-48564.

Let’s break it down: how does this vulnerability work, what’s the risk, how is it triggered, and what should you do? Here’s the story in plain English, with code examples and resources if you want to read deeper.

The Basics: What is CVE-2022-48564?

It’s a vulnerability in the standard plistlib Python library, effective in versions up to 3.9.1.

Under the hood, this bug allows an attacker to craft a *malformed* binary Plist file that, when read using plistlib's read_ints function, will consume a ridiculously large amount of CPU and RAM, potentially leading to a denial of service (DoS).

So—your server parses a malicious plist, thinking it's a config file or a settings file. Suddenly, memory and CPU usage spike. The machine becomes unresponsive. Oops.

Meet the read_ints Function

The culprit is a helper inside plistlib.py called read_ints. It reads an integer array from the binary plist file. If an attacker can put in a very large number value into the required header fields for array length or integer width, the function tries to allocate and read enormous amounts of memory, not expecting such crazy values.

Snippet from vulnerable Python (plistlib.py, simplified)

def read_ints(s, size, count):
    # Converts size to an int, reads 'count' integers of 'size' bytes from stream s
    return [int.from_bytes(s.read(size), 'big') for _ in range(count)]

If size or count are huge (because the file says so), this little function just keeps going, allocating memory and using CPU until your process or server gives up.

Attacker crafts a malicious binary plist file

- The header values for the integer array specify huge sizes and/or counts.

CPU and RAM get eaten up

- System tries to allocate (and possibly zero-fills) a massive list, killing performance or causing a crash.

Proof-of-Concept (Exploit Code Example)

Below is a simple exploit concept. This is NOT a real-world working exploit but illustrates how the vulnerability can be triggered by feeding a crafted file to plistlib.

import plistlib
import io

# Malicious plist file with a huge array field (this is just a schematic example)
# In a real exploit, you’d craft binary data with specific big size/count values.

malicious_data = (
    b'bplist00'
    b'\x10\x00\x08'  # fake object table with huge size/count encoded here
    + b'\x00' * (2**32)  # simulate massive array (placeholder, won't really run)
)

try:
    plistlib.load(io.BytesIO(malicious_data))
except Exception as e:
    print("Crash or hang detected:", e)

*WARNING:* Don’t try this on production systems—even in test, it can hang your Python process indefinitely or exhaust system resources if you make the array big enough.

Who Is at Risk?

- Any Python 3.9.1 (or older) application that reads binary plist files and does NOT validate/trust them.

Update Python!

- The bug is fixed in Python 3.9.2 and beyond.

Don’t ever process untrusted plist files directly.

- Check header fields for unrealistic array sizes/counts.

Use Resource Limits

- Run decoding in a separate process with strict memory/CPU time constraints, if feasible.

More Info

- Python Official Security Advisory, CVE-2022-48564
- Python Changelog Mentioning the Fix
- plists (Apple Developer Docs)

Summary

CVE-2022-48564 is a perfect reminder: even the “boring” parts of a software stack—like config file readers—can be risky if they don’t check for abuse. Something as harmless as a property list could let a bad actor take your app offline, just by exhausting its CPU and memory.

If you rely on plistlib in Python, update ASAP—or check your code for abuse paths. A few lines of code, left unchecked, can bring down giants!

Timeline

Published on: 08/22/2023 19:16:00 UTC
Last modified on: 10/11/2023 23:15:00 UTC