Good morning list,

I will describe here a vulnerability found in older versions of some
lightning implementations of anchor outputs. As most implementations
have not yet released support for anchor outputs, they should verify
that they are not impacted by this type of vulnerability while they
implement this feature.

I want to thank the impacted implementations for their reactivity in
fixing this issue, which hasn't impacted any user (as far as I know).

## Timeline

- March 23 2021: I discovered an interesting edge case while
implementing anchor outputs in eclair ([1]).
- August 2021: while I was finalizing support for the 0-htlc-fees
variant of anchor outputs in eclair, I was able to do in-depth
interoperability tests with other implementations that supported
anchor outputs (only lnd and c-lightning at that time). These tests
revealed that both implementations were impacted by the edge case
discovered in March and that it could be exploited to steal funds.
- September 2 2021: I notified both development teams.
- October 11 2021: I disclosed the vulnerability to Electrum and LDK
to ensure they would not ship a version of anchor outputs containing
the same issue (anchor outputs wasn't shipped in their software yet).
- November 2021: a fix for this vulnerability was released in lnd 0.14.0
and c-lightning 0.10.2.

## Impacted users

- Users running versions of lnd prior to 0.14.0
- Users running versions of c-lightning prior to 0.10.2 if they have
activated experimental features (and have anchor outputs channels)

## Description of the vulnerability

With anchor outputs, your lightning node doesn't use `SIGHASH_ALL` when
sending its signatures for htlc transactions in `commitment_signed`.
It uses `SIGHASH_SINGLE | SIGHASH_ANYONECANPAY` instead and the other
node is supposed to add a `SIGHASH_ALL` signature when they broadcast
the htlc transaction.

Interestingly, this lets the other node combine multiple htlcs in a
single transaction without invalidating your signatures, as long as the
`nLockTime` of all htlcs match. This has been a known fact for a long
time, which can be used to batch transactions and save on fees.

The vulnerability lies in how *revoked* htlc transactions were handled.
Because we historically used `SIGHASH_ALL`, we could assume that htlc
transactions had a single output. For example, older eclair versions
used that fact, and when presented with a revoked htlc transaction,
would claim a single output of that transaction via a penalty/justice
transaction (see [2]). This was completely ok before anchor outputs.
But after anchor outputs, if the revoked htlc transaction actually
contained many htlcs, your node should claim *all* of the revoked
outputs with penalty/justice transactions.

When presented with a transaction containing multiple revoked htlcs,
both impacted implementations would fail to claim any output. This means
the attacker could publish a revoked commitment with htlcs that have
been settled since then, and claim these htlcs a second time on-chain,
thus stealing funds.

Let's take a concrete example, where Bob is under attack.
Bob has channels with Alice and Carol: Alice ---> Bob ---> Carol.
Alice sends N htlcs to Carol spending all of her channel balance, which
Carol then fulfills.
Carol has then irrevocably received the funds from Bob.
Then Alice publishes her old commitment where all the htlcs were pending
and aggregates all of her htlc-timeouts in a single transaction.
Bob will fail to claim the revoked htlc outputs which will go back to
Alice's on-chain wallet. Bob has thus lost the full channel amount.

## Caveat

An important caveat is that this attack will not work all the time, so
it can carry a risk for the attacker. The reason for that is that the
htlc transactions have a relative delay of 1 block. If the node under
attack is able to make his penalty/justice transactions confirm
immediately after the revoked commitment (by claiming outputs directly
from the commitment transaction with a high enough feerate) the
attacker won't be able to broadcast the aggregated htlc transaction
(and loses their channel reserve).

The success of the attack depends on what block target implementations
use for penalty/justice transactions and how congested the mempool is
(unless the attacker notices that their peer is offline, in which case
they can use this opportunity to carry out the attack).

I'm pretty confident all users have already upgraded to newer versions
(particularly since there have been important bug fixes on unrelated
issues since then), but if your node still hasn't upgraded, you should
consider doing it as soon as possible.

Cheers,
Bastien

[1] https://github.com/ACINQ/eclair/pull/1738
[2]
https://github.com/ACINQ/eclair/blob/35b070ee5de2ea3847cf64b86f7e47abcca10b95/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala#L613
_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to