CVE-2024-22588 - How Kwik commit 745fd4e2 Left Unused Encryption Keys Hanging Around

Security vulnerabilities keep popping up, and today we’re looking at CVE-2024-22588, which was found in the “Kwik” project. If you’re not familiar, Kwik is a minimalist open-source password manager that focuses on privacy and simplicity.

A recent commit—745fd4e2—tried to improve how Kwik handled encryption. But it introduced a flaw: unused encryption keys weren’t discarded. Let’s break down why this matters, how attackers might take advantage, and what you can do about it.

What’s the Problem? (The Vulnerability Explained)

In secure software, you want to discard sensitive values (like encryption keys) once they’re no longer needed. If you don’t, those keys can stick around in memory, disk, or backups long after they’re useful. That’s a problem, because attackers who get a dump of your app’s memory, a crash log, or an old file might be able to dig up keys and decrypt your secrets.

Commit 745fd4e2 in Kwik updated key management, but didn’t securely erase keys when they became unnecessary. This means:

How Bad Is It? (Exploit Scenario)

Let’s see how an attacker could take advantage. Suppose you’re using Kwik, and you generate a new encryption key for updated passwords. The old keys are supposed to be thrown away. But with this bug, they’re not.

An attacker gains local access to your system.

2. They create a memory dump (using tools like gcore or procfs).

Example Exploit: Extracting Old Keys from Memory

Here’s some _example code_ (for educational purposes!) that could look for old keys in a memory dump:

import re

def find_possible_keys(memory_dump_file):
    with open(memory_dump_file, 'rb') as f:
        data = f.read()
    # Assume a simple 32-byte key, may need to adjust to actual Kwik key patterns
    possible_keys = re.findall(rb'[\x00-\xff]{32}', data)
    return possible_keys

keys = find_possible_keys('kwik_mem.dump')
print(f'Found {len(keys)} key candidates')

A real-world attack would refine this to search for key schedules or known plaintext checks, but you get the idea.

Here’s a simplified _bad code snippet_ highlighting the mistake

let old_key = Some(get_old_encryption_key());
// ... use the new key ...
// old_key just gets dropped whenever, not securely erased

What should have happened is something like this (in pseudocode)

let old_key = Some(get_old_encryption_key());
// ... use new key ...
securely_erase(&mut old_key);
// Now the memory holding old_key cannot be recovered

There are libraries like zeroize in Rust that overwrite memory with zeros before freeing it.

How to Fix It

The Kwik team has now merged a patch to securely wipe old keys after use. If you’re a developer, always use memory-safe key handling libraries!

If possible, rotate your master password and all stored passwords.

3. If you suspect a system compromise, consider that previously encrypted passwords might now be at risk.

Where to Learn More

- NIST: Clearing Sensitive Data
- Kwik commit 745fd4e2
- CVE-2024-22588 - NVD Entry (coming soon)
- Zeroize Rust crate

Timeline

Published on: 05/24/2024 15:15:23 UTC
Last modified on: 08/22/2024 19:35:11 UTC