Skip to content

Admin token comparison not constant-time #560

@pbeza

Description

@pbeza

The admin token comparison in dstack/kms/src/main_service.rs uses a standard byte-equality check rather than a constant-time comparison, leaking information about the token's value through response timing differences.

Root Cause

The KMS admin token verification uses a standard != comparison on hash bytes:

// main_service.rs:139-144
if provided_hash != expected_hash {
    return Err(Error::Unauthorized);
}

Standard byte comparison short-circuits on the first non-matching byte, creating a timing side-channel. An attacker can measure response times to determine how many leading bytes of the hash match, progressively recovering the admin token hash byte-by-byte.

Attack Path

  1. Attacker has network access to the KMS admin endpoint
  2. Attacker sends requests with different admin token values
  3. Attacker measures response times — longer times indicate more matching prefix bytes
  4. By iterating through possible byte values and observing timing differences, attacker recovers the admin token hash
  5. Attacker can now authenticate as admin and access all admin endpoints (including remove_cache with path traversal, a related finding)

Impact

The admin token can be recovered through timing analysis. While this requires many requests and precise timing measurements, it is a well-understood attack against non-constant-time comparisons. Compromising the admin token gives access to all admin endpoints.

Suggested Fix

Use constant-time comparison:

use subtle::ConstantTimeEq;

if !bool::from(provided_hash.ct_eq(&expected_hash)) {
    return Err(Error::Unauthorized);
}

The subtle crate provides constant-time operations specifically designed to prevent timing side-channels. ConstantTimeEq::ct_eq returns a Choice type; use bool::from() to convert it.


Note: This issue was created automatically. The vulnerability report was generated by Claude and has not been verified by a human.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions