📅 Original date posted:2023-07-06
🗒️ Summary of this message: LNbits discovered an exploit that allowed attackers to create fake balances by manipulating invoices, urging users to update their software.
📝 Original message:
Um, this is a super-weird setup AFAICT.
You generate an invoice, but you don't remember anything about it? Um,
OK, stateless invoices are a thing, but there's a metadata field for
that?
Someone pays an invoice, you don't check the place it's going (which,
y'know, signed it), you check some other field?
I've never used lnbits and I'm clearly missing something...
Thanks!
Rusty.
callebtc via Lightning-dev <lightning-dev at lists.linuxfoundation.org>
writes:
> 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
> _______________________________________________
> Lightning-dev mailing list
> Lightning-dev at lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev