Skip to content

Malicious head initialiser can extract PTs from control of Hydra scripts, leading to locked participant commits or spoofed commits

High
abailly-iohk published GHSA-9m8q-7wxv-v65p Oct 4, 2023

Package

hydra-node

Affected versions

< 0.13.0

Patched versions

0.13.0

Description

Summary

In normal use the participation tokens of a Hydra head remain under the control of the Hydra validators from the point they are minted until they are burned. Because of this, the validators can trust that a UTxO containing a PT has been progressed through the Hydra validators which come before it and been subject to the constraints and checks performed by the validators which the PT has passed through.

For example, the commit validator assumes that a UTxO residing at the commit validator containing a PT can only have progressed from the initial validator to the UTxO at the commit validator if the transaction creating the UTxO passed the checks enforced by the initial validator. In this particular case, the commit validator knows that for a UTxO containing a PT at the commit validator that specifies a reference to a committed UTxO commit_ref in its datum, the initial validator will have checked that the participant really did commit that UTxO.

A UTxO containing a PT and its data is seen as trusted, because it has been progressed through the Hydra validators and subject to their checks. Therefore if a malicious user can extract a PT from the control of the Hydra validators this trust assumption is broken, because it is no longer true that a UTxO containing a PT was subject to the checks of the Hydra validators, and the malicious user can place the PT in any UTxO with any datum they like attached at any address they wish. For example, the attacker can put the PT in a UTxO at the commit validator stating in the datum that they committed a particular UTxO, when in reality they did not really commit this UTxO which was possible because this was not checked by the initial validator, as the PT was moved from the control of the attacker to the commit validator instead of from the initial contract.

It is possible for a malicious head initialiser to extract one or more PTs for the head they are initialising due to incorrect data validation logic in the head token minting policy which then results in an flawed check for burning the head ST in the initial validator.

Details

It is possible for a malicious head initialiser to extract one or more PTs for the head they are initialising. First, in the head-initialisation transaction the attacker specifies a policy they control (attacker_cid) instead of the real head ID policy in the datum of one of the outputs at the initial validator.

image

This is possible because it is not checked in HeadTokens.hs that the datums of the outputs at the initial validator are equal to the real head ID, and it is also not checked in the off-chain code.

The UTxO resides at the initial validator and contains a PT for the real head ID. It is possible to spend UTxOs at the initial contract using one of two redeemers, viaAbort and viaCommit. If the UTxO is being redeemed using viaAbort then the only check performed is that the state token for the head is burned in the transaction, as this will mean the head validator enforces a number of rules (such as the PTs being burned).

validator commitValidator headId red context =
case red of
ViaAbort ->
traceIfFalse
$(errorCode STNotBurned)
(mustBurnST (txInfoMint $ scriptContextTxInfo context) headId)
ViaCommit{committedRefs} ->
checkCommit commitValidator headId committedRefs context

This check that the state token is burned takes the head ID from the UTxO datum, and checks that the txmint field contains datum.head_id -> "HydraHeadV1" -> (-1), but the attacker set the head ID in the datum to a policy they control instead of the real head ID; that is, datum.head_id = attacker_cid. This means that the only check done by viaAbort is that the txmint field contains attacker_cid -> "HydraHeadV1" -> (-1), which the attacker can satisfy because they control attacker_cid and can have previously minted a token named "HydraHeadV1" that they can burn in the transaction.

image

This means the attacker can spend the UTxO at the initial validator containing a PT for the head by burning the "fake" head ST they minted previously, and bypass the usual checks that would be performed by the head validator when burning the real head ST - in particular they can move the PT out of control of the Hydra validators and into their own control/wallet.

PoC

  • Attacker creates a minting policy (attacker_cid) and mints the token named "HydraHeadV1" under that policy.
  • Attacker creates an InitTx to initialise a Hydra head with head_cid, but in one of the outputs (malicious_output) at the initial contract they specify attacker_cid in the datum instead of head_cid.
  • Attacker creates a transaction which:
    • spends malicious_output with the ViaAbort redeemer
    • burns 1 of the token they minted earlier (txmint field contains attacker_cid -> "HydraHeadV1" -> (-1))
    • sends the PT for head_cid contained in malicious_output to their own wallet (or anywhere they wish)

The attacker then has control of a PT for head_cid.

Impact

During the Initial state of the protocol, if the malicious initialiser removes a PT from the Hydra scripts it becomes impossible for any other participant to reclaim any funds they have attempted to commit into the head, as to do so the Abort transaction must burn all the PTs for the head, but they cannot burn the PT which the attacker controls and so cannot satisfy this requirement. That means the initialiser can lock the other participants committed funds forever or until they choose to return the PT (ransom).

The malicious initialiser can also use the PT to spoof that they have committed a particular TxO when progressing the head into the Open state. For example, they could say they committed a TxO residing at their address containing 100 ADA, but in fact this 100 ADA was not moved into the head, and thus in order for an other participant to perform the fanout they will be forced to pay the attacker the 100 ADA out of their own funds, as the fanout transaction must pay all the committed TxOs (even though the attacker did not really commit that TxO). They can do this by placing the PT in a UTxO with a well-formed Commit datum with whatever contents they like, then use this UTxO in the collectCom transaction.

There may be other possible ways to abuse having control of a PT.

Severity

High
8.1
/ 10

CVSS base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H

CVE ID

CVE-2023-42449

Weaknesses

No CWEs

Credits