← Home ← Codex ← DEBT ← Engine
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 Attack Response Time Attack Execution Time 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.

Avoid When

  • Describing attacks on cryptographic algorithms themselves (e.g., breaking AES or RSA)—use 'side-channel attacks' or 'cryptanalysis' instead, as timing attacks on crypto primitives are a specific subset requiring different mitigations.
  • Referring to performance differences in legitimate application logic (e.g., database queries that vary by result size)—timing attacks specifically exploit information leakage from security-sensitive operations, not normal variance.
  • Discussing network latency or bandwidth as a security concern—timing attacks require measurement of operation duration, not network conditions.
  • Analyzing brute-force attacks that succeed through sheer computational cost—timing attacks rely on differential timing signals to narrow the search space, not raw speed.

When To Use

  • You're reviewing code that compares HMAC tokens, API keys, or session identifiers using standard string comparison operators — switch to constant-time comparison immediately to block character-by-character recovery.
  • You're designing a password reset or account recovery flow where an attacker can submit many guesses and measure response times — use constant-time token validation to eliminate the timing side-channel.
  • You're assessing whether a legacy authentication system is vulnerable to side-channel attacks, especially in internal networks or cloud environments where an attacker has low-latency access to the server.
  • You're implementing signature or HMAC verification for APIs or webhooks — always use a constant-time comparison function to prevent attackers from forging valid signatures by exploiting timing differences.

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 6 Sep 2026
Views 109
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 1 ping S 0 pings S 1 ping 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 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M
No pings yet today
No pings yesterday
SEMrush 12 PetalBot 9 Google 7 Ahrefs 7 Bing 5 Claude 4 Scrapy 3 Sogou 3 Applebot 2 ChatGPT 1 Perplexity 1 Unknown AI 1 Qwen 1 Meta AI 1 Twitter/X 1
crawler 57 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