Why Nostr? What is Njump?
2023-06-19 19:42:41
in reply to

callebtc [ARCHIVE] on Nostr: 📅 Original date posted:2023-06-19 🗒️ Summary of this message: LNbits ...

📅 Original date posted:2023-06-19
🗒️ Summary of this message: LNbits discovered an exploit that allows attackers to create balances out of thin air by abusing a quirk in how invoices are handled internally. The attacker can insert a bolt-11 payment hash of payment A into a different payment, creating a malicious invoice B that can trick the backend into believing that B == A. The mitigation is simple, and developers should use additional checks to ensure that the invoice details have not been messed around with. The attack requires a fundamental understanding of bolt-11 and custom tooling to produce the malicious invoice.
📝 Original message:
Dear list,

earlier last month, our team at LNbits discovered a rather interesting exploit which wich would enable an attacker to create balances out of thin air by abusing a quirk in how invoices are handled internally. We've patched this in LNbits version 0.10.5 and urge anyone to update ASAP if you haven't done so already. I want to describe the attack here, since my gut feeling is that carrying out the same exploit is possible in other Lightning applications. If you're working on custodial wallets, payment processors, account management software, etc. you probably want to read this.

In short, the attacker was able to insert a bolt-11 payment hash of payment A into a different payment, creating a malicious invoice B that can trick the backend into believing that B == A.

Here is how it goes:

- Attacker creates invoice A of amount 1000 sat in LNbits
- Attacker creates invoice B' of amount 1 sat on her own node
- Attacker deserializes B', inserts payment_hash(A) into payment_hash(B), re-signs the invoice, and serializes it again, producing malicious invoice B
- Attacker creates a new account in LNbits and pays B

- LNbits backend uses payment_hash(B) to check whether this is an internal payment or a payment via LN
- Backend finds A in its database since we implicitly assume that payment_hash(A) commits to A

** This is the critical part! Payment hashes do *NOT* commit to any payment details (like amount) but only to the preimage! **

- Backend settles payment internally by crediting A debiting B
- Attacker has "created" 999 sats

Mitigation:

The mitigation is quite simple. Backends should either use self-generated unique "checking id's" for looking up internal payments or use additional checks to make sure that the invoice details have not been messed around with (e.g., asserting amount(A) == amount(B)).

Lessons:

I think there are two lessons here. First, it's good to realize the level of sophistication of LN-savvy attackers. This attack clearly involves a fundamental understanding of bolt-11 and requires custom tooling to produce the malicious invoice.

The second lesson is more valuable: The "payment hash" of an invoice is not a "payment" hash but merely a "preimage" hash – and nothing else. Naming this field as such increases the chance of developers implicitly assuming that the hash commits to payment details like amount, pubkey, etc. I will from now on call this simply the "preimage hash" and invite you to do so too.

Best

Calle
Author Public Key
npub1wlhtt0d2g4yu7plwqq4rnwfrda8du7xlvs8v57c32u0wear0v8tq6h90xk