← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Timing Attacks

Security CWE-208 Advanced
debt(d5/e1/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep and phpstan as the tools that catch the pattern of == or === comparing hash_hmac() outputs or token strings. These are not default linters but specialist SAST tools that require deliberate configuration, placing this squarely at d5.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix is explicit: replace == or strcmp() with hash_equals($known_good, $user_supplied). This is a single-call swap at each comparison site, so e1 is the correct anchor, though multiple call sites may exist independently.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The fix applies at each token/HMAC comparison point rather than spreading across the whole architecture. It is a recurring tax wherever secrets are compared, but each site is self-contained and the rest of the codebase is unaffected, keeping burden at b3.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field states that developers widely believe timing attacks are theoretical or impractical, but in reality same-datacenter or cloud-colocated attackers can exploit sub-millisecond differences with enough samples. Additionally, the common_mistakes show that even hash_equals() has a subtlety around length mismatches that can still leak information, contradicting the assumption that switching to hash_equals() is fully sufficient without normalising lengths. This combination of 'looks safe but isn't' plus 'the obvious replacement also has a gotcha' lands at t7.

About DEBT scoring →

Also Known As

timing side-channel constant-time comparison hash_equals side-channel attack

TL;DR

Side-channel attacks that infer secret values by measuring how long an operation takes — a string comparison that short-circuits on the first mismatch leaks information about the secret one character at a time.

Explanation

A timing attack exploits the fact that standard string comparison (== or strcmp) returns early as soon as a mismatch is found — comparing 'abc' against 'xyz' takes less time than comparing 'abc' against 'abd'. An attacker who can make many requests and measure response times can recover a secret (HMAC token, API key, password reset token) one character at a time by submitting guesses and choosing the one that takes longest. PHP's hash_equals() performs constant-time comparison — it always inspects every byte regardless of where the first difference occurs, eliminating the timing signal. password_verify() is already constant-time. The attack is especially realistic for HMAC signature verification, API key comparison, and password reset token validation where the secret is a fixed-length string. Network jitter limits practical exploitation over the internet, but server-local or same-datacenter attacks are very feasible.

Watch Out

Even hash_equals() leaks timing info if the two strings have different byte lengths — always compare fixed-length hashes (e.g. hash the user input before comparing) so both inputs are the same length.

Common Misconception

Timing attacks are not theoretical — same-datacenter or cloud-colocated attackers can measure sub-millisecond differences with enough samples to recover tokens, even with network noise.

Why It Matters

Any code that compares a secret token using == is vulnerable — HMAC verification, API key checks, and password-reset token comparison must all use hash_equals() or an equivalent constant-time function.

Common Mistakes

  • Using === or == to compare HMAC signatures or API tokens — both short-circuit and leak timing information.
  • Using strcmp() for security-sensitive comparisons — also non-constant-time.
  • Comparing tokens of different lengths with hash_equals() — the function returns false immediately for length mismatches in some implementations; normalise length before comparing or use a fixed-length hash of both sides.

Code Examples

💡 Note
The bad example uses === which short-circuits — an attacker measuring webhook response times can recover the HMAC secret. hash_equals() always compares all bytes, producing identical timing regardless of where strings differ.
✗ Vulnerable
// Vulnerable — short-circuits on first mismatch:
if ($request->header('X-Signature') === hash_hmac('sha256', $payload, $secret)) {
    processWebhook($payload);
}
✓ Fixed
// Constant-time comparison:
$expected = hash_hmac('sha256', $payload, $secret);
$received = $request->header('X-Signature') ?? '';
if (!hash_equals($expected, $received)) {
    throw new InvalidSignatureException();
}
processWebhook($payload);

Added 10 Apr 2026
Edited 12 Jun 2026
Views 36
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W 0 pings T 1 ping F 0 pings S 2 pings S 0 pings M 1 ping T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
SEMrush 6 Ahrefs 3 Scrapy 3 Google 2 Claude 2 Bing 2 ChatGPT 1 Perplexity 1 Unknown AI 1 Qwen 1 Meta AI 1 PetalBot 1
crawler 23 crawler_json 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Replace == or strcmp() with hash_equals($known_good, $user_supplied) for all token and HMAC comparisons
🔗 Prerequisites
🔍 Detection Hints
=== or == comparing hash_hmac(), token strings, or API keys directly
Auto-detectable: ✓ Yes semgrep phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-208 CWE-697


✓ schema.org compliant