CVE-2024-0436 - Understanding the Timing Attack Risk in Single-User Password Mode

In early 2024, a new vulnerability labeled CVE-2024-0436 surfaced, drawing attention to an often overlooked aspect of web application security: how password comparison is implemented. This vulnerability highlights how poor handling of password checks can, in theory, open the door for a timing attack. The issue arises from the use of the strict inequality operator (!==) for password comparison in single-user password-protected applications.

In this post, we'll break down what CVE-2024-0436 is, examine why the vulnerability exists, and show—with easy code snippets—how an attacker might try to exploit it. We'll also explain why the real-world risk is lower, but not zero.

What Is a Timing Attack?

A timing attack is a side-channel attack where the attacker measures how long a system takes to process a request and uses that information to guess secrets (like passwords). If different inputs take noticeably different amounts of time to handle, the attacker can gradually deduce the correct input character by character.

For password checks, the risk comes from comparing the passwords in a way that exits early if a mismatch is found ("linear comparison"). This can leak which part of a password is correct.

A lot of quick-and-simple web apps use a single password, compared like this

if (inputPassword !== actualPassword) {
    throw new Error('Incorrect password!');
}

This looks fine at first glance. But here's the problem: the !== operator checks each character in order and returns as soon as it finds a mismatch. If an attacker notices that supplying a password starting with the correct first letter takes slightly longer, they can keep guessing one character at a time, measuring response time.

Here's a simplified version of the vulnerable comparison logic

function checkPassword(inputPassword, realPassword) {
    if (inputPassword.length !== realPassword.length) {
        return false;
    }
    for (let i = ; i < realPassword.length; i++) {
        if (inputPassword[i] !== realPassword[i]) {
            return false;
        }
    }
    return true;
}

If the first character matches, it takes just a bit longer to reject than if the first one doesn't match. If the first _two_ match, it's slower still, and so on. That's enough to start brute-forcing with timing!

The attacker would send many guesses to the server, like

POST /login
password: aaaaaaa
# Measure response time

POST /login
password: baaaaaa
# Measure response time

...

They look for requests that take slightly longer, which means more characters matched at the start. Automation tools and thousands of guesses can "walk through" the password, one character at a time.

While the comparison is not constant-time, practical exploitation is difficult because of

1. Network Variability: Real web requests have inconsistent response times due to network conditions, server load, etc.
2. Framework Overhead: The actual application and network stack add unpredictable delays that make measurement "noisy."

So, while theoretical timing attacks are possible, reliably pulling off such an attack over the public internet (or most networks) is extremely hard.

How to Fix It

Developers should always use constant-time comparison for secrets like passwords. Here's an example fix using Node.js crypto.timingSafeEqual:

const crypto = require('crypto');

function secureCompare(a, b) {
    // Both should be Buffer and same length
    return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}

Now, it doesn't matter how many characters match; the function always takes the same amount of time.

References

- CVE-2024-0436 at CVE.org
- OWASP: Timing Attack
- Node.js Crypto: timingSafeEqual

Conclusion

CVE-2024-0436 reminds us that how you compare sensitive data can be as important as what you compare. Even small mistakes like using !== for passwords can (theoretically) lead to password leaks over time.

If you build web services—always use constant-time comparison for passwords. Even if the attack is tricky in the real world, it's best not to take chances. Stay safe out there!


*This post is written for educational purposes and aims to help developers avoid common password handling mistakes.*

Timeline

Published on: 02/26/2024 16:27:50 UTC
Last modified on: 02/26/2024 16:32:25 UTC