Skip to content

Signature concatenation without length prefixes enables collision #554

@pbeza

Description

@pbeza

The VerifiedReport construction in dstack/kms/src/main_service.rs concatenates the report body and signature without a length delimiter, so a crafted report could shift bytes between the body and signature fields while preserving the concatenation.

Root Cause

The KMS signing function computes Keccak256(prefix + ":" + appid + message). While a colon delimiter separates prefix from appid, there is no delimiter or length prefix between appid and message. Since both are variable-length byte strings, different (appid, message) pairs can produce the same concatenation and therefore the same hash.

// crypto.rs:32-43
let hash = Keccak256::digest(&[prefix.as_bytes(), b":", app_id.as_bytes(), message].concat());

Attack Path

  1. App A has app_id = "abc" and signs message = "defGHI"
  2. App B has app_id = "abcdef" and signs message = "GHI"
  3. Both produce Keccak256("prefix:abcdefGHI") — identical hashes
  4. App B's signature is valid for App A's (app_id, message) pair
  5. This enables cross-app signature forgery between apps whose app_ids share prefixes

Impact

Signature confusion between different apps. An attacker who controls one app can forge signatures that appear to come from a different app whose app_id is a prefix of the attacker's app_id (or vice versa). The practical impact depends on how signatures are verified downstream.

Suggested Fix

Add a delimiter or length prefix between app_id and message:

let hash = Keccak256::digest(
    &[
        prefix.as_bytes(),
        b":",
        &(app_id.len() as u32).to_be_bytes(),
        app_id.as_bytes(),
        message,
    ]
    .concat(),
);

Alternatively, use a structured encoding (e.g., RLP, SSZ, or CBOR) for the hash preimage.


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