Timing Attacks in Node.js

Let’s start from the very beginning: What a timing attack is (CWE‑208), why it matters in Node.js, and exactly how you can stop it. CWE stands for Common Weakness Enumeration, a catalog of software security flaws. CWE‑208 covers flaws where an attacker learns secret data (passwords, keys, etc.) simply by measuring how long certain operations take. if your code takes a slightly different amount of time depending on secret data, an attacker can “listen to the clock” and gradually recover that secret. What’s a timing (side‑channel) attack? The side‑channel idea Imagine you’re behind a curtain watching two people entering a dark room and opening a safe with a code lock. You can’t see the lock, but you hear the clicks. If one person pauses longer before entering the final digit, you realize they got three digits right and hesitated on the fourth. By measuring those pauses, you learn the code—without ever seeing it. In computing, a side‑channel is any unintended “signal” (time, power use, sound) that leaks information about what’s happening inside. A timing attack is a side‑channel attack that focuses on tiny time differences. Why timing matters Most programming languages stop a compare operation (“do these two values match?”) as soon as they find a mismatch. Compare abcX vs abcY: mismatch on the 4th character → stop after 4 checks. Compare a000 vs b000: mismatch on the 1st character → stop after 1 check. An attacker can repeatedly try different guesses and carefully measure “how long did the server take to reject it?” Over thousands of requests, those micro‑differences reveal which characters were matching. How do timing leaks show up in Node.js? Node.js, by default, uses C libraries or pure‑JavaScript routines that often bail out early on a mismatch. Common pitfalls: 1.String or buffer comparison: if (userInput === secret) { /* … */ } Behind the scenes, this is a variable‑time operation. 2.Conditional logic on secrets: if (password.startsWith('admin')) { // do something slower } else { // do something faster } Even tiny branches can leak a few microseconds. 3.Hashing without constant‑time checks: You compute a hash of the password, then do hash === storedHash. That comparison can leak. Example: leaking a 4‑digit PIN 1.Attacker sends PIN “0000” → server checks 0 vs stored 0 (✓), then 0 vs stored 0 (✓), then 0 vs stored 0 (✓), then 0 vs stored 1 (✗) → rejects after 4 steps → takes 1.2 ms. 2.Attacker sends “0001” → mismatch on 4th step → also ~1.2 ms. 3.Attacker sends “0010” → mismatch on 3rd step → takes ~0.9 ms. By comparing 1.2 ms vs 0.9 ms, the attacker knows the first two digits were correct (“00”) and the third was wrong. In a handful of rounds, all four digits leak.

Apr 22, 2025 - 11:43
 0
Timing Attacks in Node.js

Let’s start from the very beginning:

What a timing attack is (CWE‑208), why it matters in Node.js, and exactly how you can stop it.

  • CWE stands for Common Weakness Enumeration, a catalog of software security flaws.

  • CWE‑208 covers flaws where an attacker learns secret data (passwords, keys, etc.) simply by measuring how long certain operations take.

if your code takes a slightly different amount of time depending on secret data, an attacker can “listen to the clock” and gradually recover that secret.

micheal scot

What’s a timing (side‑channel) attack?

The side‑channel idea

Imagine you’re behind a curtain watching two people entering a dark room and opening a safe with a code lock. You can’t see the lock, but you hear the clicks.

If one person pauses longer before entering the final digit, you realize they got three digits right and hesitated on the fourth. By measuring those pauses, you learn the code—without ever seeing it.

In computing, a side‑channel is any unintended “signal” (time, power use, sound) that leaks information about what’s happening inside.

A timing attack is a side‑channel attack that focuses on tiny time differences.

Why timing matters

Most programming languages stop a compare operation (“do these two values match?”) as soon as they find a mismatch.

  • Compare abcX vs abcY: mismatch on the 4th character → stop after 4 checks.
  • Compare a000 vs b000: mismatch on the 1st character → stop after 1 check.

An attacker can repeatedly try different guesses and carefully measure “how long did the server take to reject it?”

Over thousands of requests, those micro‑differences reveal which characters were matching.

How do timing leaks show up in Node.js?

Node.js, by default, uses C libraries or pure‑JavaScript routines that often bail out early on a mismatch. Common pitfalls:

1.String or buffer comparison:

if (userInput === secret) { /* … */ }

Behind the scenes, this is a variable‑time operation.

2.Conditional logic on secrets:

if (password.startsWith('admin')) {
  // do something slower
} else {
  // do something faster
}

Even tiny branches can leak a few microseconds.

3.Hashing without constant‑time checks:

You compute a hash of the password, then do hash === storedHash. That comparison can leak.

Example: leaking a 4‑digit PIN

1.Attacker sends PIN “0000” → server checks 0 vs stored 0 (✓), then 0 vs stored 0 (✓), then 0 vs stored 0 (✓), then 0 vs stored 1 (✗) → rejects after 4 steps → takes 1.2 ms.

2.Attacker sends “0001” → mismatch on 4th step → also ~1.2 ms.

3.Attacker sends “0010” → mismatch on 3rd step → takes ~0.9 ms.

By comparing 1.2 ms vs 0.9 ms, the attacker knows the first two digits were correct (“00”) and the third was wrong.

In a handful of rounds, all four digits leak.