Skip to content

Instantly share code, notes, and snippets.

@ariard
Last active June 18, 2022 03:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ariard/6bdeb995565d1cc292753e1ee4ae402d to your computer and use it in GitHub Desktop.
Save ariard/6bdeb995565d1cc292753e1ee4ae402d to your computer and use it in GitHub Desktop.
# Problem
In case of a relayed HTLC hash-and-amount collisioning with a expected payment HTLC on the same
channel, LND was releasing the preimage for the later while claiming onchain the former. A malicious
peer could have deliberatelt intercept a HTLC intended for the victim node, probe the victim to learn
the preimage and steal the intercepted HTLC.
Prior to v0.11, LND had a vulnerability in its invoice database while claiming onchain a received
HTLC output, it didn't verify that the corresponding outgoing off-chain HTLC was already settled
before releasing the preimage. In case of hash-and-amount collision with an invoice, the preimage
for an expected payment was instead released. A malicious peer could have deliberately intercept
a HTLC intended for the victim node, probe the preimage through a colluding relayed HTLC and steal
the intercepted HTLC.
Note that MPP payments (invoices with `s` field`) aren't subjects to this vulnerability as an attacker
wouldn't have the payment secret to authenticate the probe HTLC.
This vulnerability was exposing routing nodes also receiving payments. A peer servicing as an
intermediary hop of a payment path could have guess that the next hop is a the final receiver
by comparing the HTLC's `amount_msat` with any goods/services advertised by the victim node
merchant website. This is not affecting non-routing nodes.
# Solution
The current spec requiremet is the following :
"A local node if it receives (or already posseses) a payment preimage for an unresolved HTLC output
that it has been offered AND for which is it has committed to an outoing HTLC MUST resolve the
output by spending it, using the HTLC-Success transaction".
This point could be clearer and precise the risk of HTLC hash-and-amount collision.
"MUST NOT reveal a preimage for an incoming HTLC if it has not learnt the preimage for the
claiming of the outgoing HTLC"
That said, with the deployment of `payment_secret`, this specific risk should be less of a concern.
# Background
Alice, a merchant, is sending an invoice for amount A and hash H to Bob.
Bob is routing the HTLC A/H to Alice through Mallory.
Channel topology [0]
HTLC (A,H') HTLC (A,H') HTLC (A,H)
_____________ _____________ _____________
/ \ / \ / \
V \ V \ V \
Mallet <-----------> Alice <------------> Mallory <-----------> Bob
\ ^
\______________________________________/
invoice (A,H)
Mallory intercepts HTLC (A,H) from Bob and doesn't relay it forward. Mallory, knowing that Alice
node pubkey is tied to a merchant node, is browsing through her goods/services index to decide
if Bob's HTLC is intended for Alice by comparing the relayed amount with the price of an item.
If there is a match, more-or-less some noise of sats, Mallory draws a new payment path to Mallet,
a colluding node. Mallory sends a HTLC (A,H') to Alice, which relays it forward to Mallet.
Mallet holds the HTLC and doesn't it immediately. Instead, Mallet route back a new HTLC Y to
Mallory through Alice. This HTLC Y won't be failed by Mallory, thus forcing Alice to force-close
the channel when HTLC Y off-chain settlement deadline is crossed.
Alice goes onchain with her commitment for chan Alice-Mallory. She claims back offered output for
HTLC Y and received output for HTLC H'. She reveals preimage P, with H'=sha256(P) equivalent to
H=sha256(P).
Mallory learns preimage P onchain and sends it out-of-band to Mallet which claims the incoming
HTLC H' from Alice. Mallory claims the previously intercepted HTLC H from Bob.
Bob learns the preimage P.
The coalition Mallet and Mallory gain the value of HTLC H minus Alice's routing fee for HTLC H'.
Also, they may have pay the channels opening/closing fees depending on who initiates.
Alice reveals a preimage P which corresponds to a provided good/service without receiving the
payment for it, thus being at loss.
Alice might not have learnt about her loss until reconciliating her merchant inventory with
her HTLC accounting, thus this exploitation might have been stay stealth for a while.
# Discovery
While working on Rust-Lightning, I observed that the specification was silent on the risk of
hash collision during the onchain operations. I surveyd deployed Lightning implmentations on this
behavior. A quick manual test against LND (65f5119) confirmed this vulnerability, which has
been immediately disclosed to LND team.
We agreed for a 6-month embargo period, as at that time a LND release (0.10) was
undergoing and it was too late to implement a covert fix in this release.
If this vulnerability has been exploited, the original sender would have discovered the preimage,
according to the pre-agreed invoice but without the issuer effectively being paid. In case of legal
disagreement if the corresponding good/service should be settled, and assuming parties were subject
to the same juridiction, it could have been an interesting case to decide if the invoice/preimage pair
is legally binding.
# Timeline
2020-04-19: Vulnerability discovered, LND team notified
2020-04-29: lnd v0.10.0-beta released (without fix)
2020-07-31: lnd v0.11-0-beta released (with fix)
2020-10-08: Partial Disclosure, encouraging lnd users to upgrade to lnd v0.11.x ASAP
2020-10-20: Full Disclosure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment