39829 [W&A-Critical] dos archiver via data subscription channel due to broken safestringfy

#39829 [W&A-Critical] DOS archiver via data subscription channel due to broken safeStringfy

Submitted on Feb 8th 2025 at 15:22:49 UTC by @ZhouWu for Audit Comp | Shardeum: Ancillaries III

  • Report ID: #39829

  • Report Type: Websites and Applications

  • Report severity: Critical

  • Target: https://github.com/shardeum/archive-server/tree/itn4

  • Impacts:

    • Taking down the application/website

Description

Description

Archiver has a data subscription service via websocket to core and store these data to a disk. During the write to disk, archiver will do the stringify operation to the data. The problem lies within the stringify function that shardus custom implemented. The safestringify function will try to stringify a buffer object with the supplied length without actually checking if the content are actually valid. This lead to extreme memory allocation of archiver and eventually crashing.

This is the affected area of code in archiver /src/Data/Collector.ts

    ...more code
    if (missingReceiptsMap.has(tx.txId)) missingReceiptsMap.delete(tx.txId)
    receipt.beforeStates = globalModification || config.storeReceiptBeforeStates ? receipt.beforeStates : [] // Store beforeStates for globalModification tx, or if config.storeReceiptBeforeStates is true
    combineReceipts.push({
      ...receipt,
      receiptId: tx.txId,
      timestamp: tx.timestamp,
      applyTimestamp,
    })
    if (config.dataLogWrite && ReceiptLogWriter)
      ReceiptLogWriter.writeToLog(
        `${StringUtils.safeStringify({
          ...receipt,
          receiptId: tx.txId,
          timestamp: tx.timestamp,
          applyTimestamp,
        })}\n`
      )
    txDataList.push({ txId, timestamp })
    // If the receipt is a challenge, then skip updating its accounts data or transaction data
    // if (
    //   config.newPOQReceipt === true &&
    //   appliedReceipt &&
    //   appliedReceipt.confirmOrChallenge &&
    //   appliedReceipt.confirmOrChallenge.message === 'challenge'
    ...more code

Proof of Concept

Proof of Concept

In real network, this patch will be deployed to only a malicious node but to make testing process easier during demonstration of the exploit, let's applied these patch to all nodes. We'll only enable the attack on the node that maintain web-socket data subscription with archiver later.

  1. Apply core patch

  1. link to shardeum repo and launch the network.

  2. After a couple of cycle node should come online.

  3. At this point you can check the archiver logs inside instances folder to see which node is subscribed by the archiver and call the /attack on that node

  4. Alternatively I prepare a script to help you with step 4. which turn on attack on all node.

  5. Paste the code into exploit.js

  1. And this content into the package.json then do npm i afterward.

  1. Run the exploit node exploit.js

  2. Observe the large memory allocation in archiver process, unresponsive practically crashing and DOSing it.

Impact

Can cause the DOS of archive servers.

Last updated

Was this helpful?