Hi,

In this post, I would like to expose a potential vulnerability introduced
by the recent anchor output spec update related to the new usage of
SIGHASH_SINGLE for HTLC transactions. This new malleability combined with
the currently deployed mechanism of `update_fee` is likely harmful for
funds safety.

This has been previously shared with deployed implementations devs, as
anchor channels are flagged as experimental it's better to discuss and
solve this publicly. That said, if you're currently running experimental
anchor channels with non-trusted parties on mainnet, you might prefer to
close them.

# SIGHASH_SINGLE and `update_fee` (skip it if you're familiar)

First, let's get started by a quick reminder of the data set committed by
signature digest algorithm of Segwit transactions (BIP 143):
* nVersion
* hashPrevouts
* hashSequence
* outpoint
* scriptCode of the input
* value of the output spent by this input
* nSequence of the input
* hashOutputs
* nLocktime
* sighash type of the signature

Anchor output switched the sighash type from SIGHASH_ALL to SIGHASH_SINGLE
| SIGHASH_ANYONECANPAY for HTLC signatures sent to your counterparty. Thus
it can spend non-cooperatively its HTLC outputs on its commitment
transactions. I.e when Alice broadcasts her commitment transaction, every
Bob's signatures on Alice's HTLC-Success/Timeout transactions are now
flagging the new sighash type.

Thus `hashPrevouts`, `hashSequence` (ANYONECANPAY) and `hashOutputs`
(SINGLE) aren't committed anymore. SINGLE only enforces commitment to the
output scriptpubkey/amount at the same index that
the spending input. Alice is free to attach additional inputs/outputs to
her HTLC transaction. This change is aiming to let a single-party bump the
feerate of 2nd-stage HTLC transactions in case of mempool-congestion,
without counterparty cooperation and thus make HTLC funds safer.

The attached outputs are _not_ encumbered by a revokeable redeemscript for
a potential punishment.

That said, anchor ouput spec didn't change disable the current fee
mechanism already covering HTLC transactions. Pre/post-anchor channels are
negotiating a feerate through `update_fee` exchange, initiated by the
channel funder. This `update_fee` can be rejected by the receiver if it's
deemed unreasonable compared to your local fee estimator view, but as of
today implementations are pretty liberal in their acceptance, admitting a
divergence from a scale of 1 to no-bound at all.

This negotiated feerate (`feerate_per_kw`) is used by channel participants
to compute effective fees which have to be deduced either from the funder
balance output for commitment transactions or from HTLC output value for
HTLC transactions.

# The Vulnerability : a Penalty Escape Vector

By increasing the feerate thanks to `update_fee`, a malicious party can
inflate fees committed on HTLC input/output pairs and redirect this
inflated fee to a single-controlled output attached to these malleable
pairs. This won't be punishable by an honest party in case of revoked state
broadcast and thus enable to partially escape the penalty.

As an example, Alice and Bob have a 100_000 sats channel. `feerate_per_kw`
is 10000 sats.

At state N, Alice balance is all on her side. She announces 10 outgoing
HTLCs of value 7000 sats.

As Commitment tx weight with 10 outputs is 2844 (post-anchor), the absolute
fee committed is 28440 sats.

As HTLC-timeout weight is 666 (post-anchor), the absolute fee committed is
of 6660 sat, the HTLC tx output as counter-signed by Bob is of 340 sat.
This absolute fee aims to pay the miner fee in case Alice needs to timeout
HTLC onchain.

Her remaining balance is 1560 sat, above both dust_limit_satoshi and the
channel reserve as constrained by Bob (likely 1%).

Alice waits for HTLCs to expire and advances state to N+1. Then she empties
her balance minus reserve by sending a HTLC relayed by Bob either to a
colluding channel on the rest of network or back to an onchain address
thanks to a swap service.

At state N+2, Alice finalizes HTLC-timeout of state N by capturing almost
all of the absolute fee to a new P2WPKH output only controlled by her. She
broadcasts the revoked commitment tx N and burns 28440 sats in commitment
fee.

Her balance of 1560 sats is punished by Bob's justice transaction.

After confirmation and thus maturing of the CSV of 1 on her HTLC output
Alice broadcasts her 10 HTLC-timeout sending back to her 6660 sat - 660 to
pay a low-fee. Bob punishes the 10 HTLC-timeout outputs of 340 sats.

Alice gain =  99_000 (swap spend) + 66_660 (HTLCs escape) - 1560
(commitment balance punishment) - 28440 (commitment fee) - 660*10 (HTLCs
fees) - 340*10 (HTLCs output) = 125600 sats.

Alice's gain is superior at channel value as it has been partially
double-spend by bypassing the revocation punishment.

# Limitations of Attacker Success

A first limitation of attack success which can be point of is the fact that
post-anchor HTLC outputs are CSV'ed by 1, which means in theory a honest
party can punish this output before the malicious spend them with the
revoked HTLC txn. In practice a malicious party can attach a branch of
descendants to its anchor output and that way only allowing one more
mempool victim's transaction on the revoked commitment. The victim must
spend all outputs at once or otherwise they're going to obstrucate each
other at mempool acceptance.

Secondly, other limitations  are the per-implementation channel policy
`max_accepted_htlcs`, `max_htlc_value_in_flight`, `channel_reserve` and
acceptance bound of `update_fee`. A quick look at default policies, even if
they vary between deploy implementations, let it think there is room to
escape a substantial part of channel value.

Lastly, after the revoked commitment transaction is confirmed, both
attacker and victim are in a feerate race to confirm either a justice
transaction or a malicious HTLC-timeout. As fee estimator logic of the
victim's implementation is a public piece of knowledge, it shouldn't be
hard for the attacker to know the range of the first fee bid and override
it by a bit to confirm it before the victim RBF at next block. Currently,
not all implementations have RBF of justice transactions.

As of today, if anchor output is deployed and given how LN implementations
are managing fees/rebroadcast of onchain transactions, the chance of attack
success sounds high in my opinion.

# Countermeasures

Channel policies could be tighter, like bounded further down
`max_accepted_htlcs` or restraining acceptance of `update_fee`. For the
latter, it's pretty hard as a) fee estimators diverge on mempool views b)
an attacker can craft escape HTLC-txn in a period of high-fee and patiently
waits a low-fee period to launch the exploitation.

Justice transactions can adopt a scorched earth approach binding their
feerate to the max to increase odds of winning the feerate race and thus
deter attackers. But this sounds like introducing a griefing attack vector.
Your counterparty can burn more of your lawful balance in fees than you'll
punish its revoked balance.

A workable option would be to patch current anchor spec to remove
`feerate_per_kw` appliance on 2nd-stage transactions, maybe just committing
a minimal relay fee.

Thoughts of further countermeasures ?

I think the vulnerability described is mostly right but please point any
missing details.

Cheers,

Antoine
_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to