Skip to content

[BUG] Signature Replay Attack - No Nonce Protection #135

@frozenflux2

Description

@frozenflux2

Project

term-challenge

Description

The authentication system uses timestamp-based replay protection with a 5-minute window, but does NOT track used signatures. This allows replay attacks where an attacker can reuse a valid signature multiple times within the 5-minute window.

Error Message

No error - replay attacks succeed silently
Same signature accepted multiple times within 5-minute window

Debug Logs

// src/crypto/auth.rs lines 120-125
/// Check if a timestamp is within the acceptable window (5 minutes)
pub fn is_timestamp_valid(timestamp: i64) -> bool {
    let now = chrono::Utc::now().timestamp();
    let window = 5 * 60; // 5 minutes
    (now - timestamp).abs() < window
}

// No tracking of used signatures anywhere in the codebase!
// grep -rn "used_signature\|signature.*used\|nonce.*track" src/ returns 0 matches

System Information

- Bounty Version: 0.1.0
- OS: Ubuntu 24.04 LTS
- Rust: 1.75+

Screenshots

No response

Steps to Reproduce

  1. Capture a valid signed request (e.g., via network sniffing or logs):
{
  "validator_hotkey": "5Freal...",
  "signature": "0xabc123...",
  "timestamp": 1705700000,
  "count": 5
}
  1. Replay the exact same request multiple times within 5 minutes:
# Attacker replays 100 times in 5 minutes
for i in {1..100}; do
  curl -X POST .../claim_jobs -d '{same payload}'
done
  1. All requests succeed because no nonce/replay tracking exists

Expected Behavior

  1. Each signature should only be usable ONCE
  2. Server should track used signatures (nonce table)
  3. Duplicate signatures should be rejected with "Signature already used"

Actual Behavior

  • Signatures can be replayed unlimited times within 5-minute window
  • No database table tracking used signatures
  • No nonce in signature message

Affected endpoints:

  • claim_jobs - Attacker can steal all jobs
  • heartbeat - Attacker can fake validator status
  • log_task - Attacker can replay task results
  • submit - Attacker can replay submissions

Additional Context

Recommended fix:

  1. Add nonce to signature message:
let message = format!("claim_jobs:{}:{}", timestamp, random_nonce);
  1. Track used signatures in database:
CREATE TABLE used_signatures (
    signature_hash TEXT PRIMARY KEY,
    used_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
  1. Check before accepting:
fn is_signature_valid(sig: &str, ...) -> bool {
    let sig_hash = sha256(sig);
    if db.signature_exists(&sig_hash) {
        return false; // Replay attack!
    }
    db.mark_signature_used(&sig_hash);
    true
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions