Newsticker

Ein neuer Angriff auf Lightning ersetzt unbestätigte Transaktionen und schadet Routing-Nodes

Bild von BLM Nevada via flickr.com. Lizenz: Creative Commons

Es gibt wieder einen Lightning-Bug. Der Angriff ist, je nach Experte, harmlos bis schwer, und die Schutzmaßnahmen, die alle Lightning-Clients ergriffen haben, nutzlos bis durchgreifend. Die Fachleute sind sich also noch uneins — doch interessant ist der Angriff allemal.

Vergangene Woche hat der Entwickler Antoine Riard in der Lightning-Mailing-List einen neuen Angriff auf Lightning veröffentlicht. Dieser Angriff ist äußerst kompliziert, und die Ansichten der Entwickler, wie gefährlich er ist, weichen ungewöhnlich stark voneinander ab.

Einigermaßen klar ist aber: 1.) der Exploit CVE 40231-40234 wurde bisher noch nicht „in Echt“ ausgenutzt, 2.) ist vollständig nur auf der Ebene von Bitcoin Core und den Minern auszumerzen und 3.) kann neue Klasse von Angriffen begründen, die über Lightning hinausgehen. Es gibt also keinen Anlass zur Panik – aber auch nicht zur Entwarnung.

Es handelt sich um eine „Transaction Replacement Cycling Attack“, also einen Angriff, der Transaktionen wiederholt aus dem Mempool ersetzt. Anfällig für ihn sind Routing-Nodes, die Zahlungen weiterleiten. Sie können Geld verlieren, indem sie Bitcoins an den Empfänger einer Zahlung weiterleiten, ohne vom Sender die entsprechende Menge Satoshi zu erhalten.

Alle gängigen Clients haben bereits Schutzmaßnahmen eingerichtet. Wer seinen Routing-Node nicht aktualisiert hat, sollte das nachholen. Benutzer von „normalen“ Wallets, wie Phoenix oder Wallet of Satoshi, sind nicht betroffen.

Zeitschlösser und Urbilder

Berichtet wurde der Bug von Antoine Riard, ein erfahrener Bitcoin-Entwickler, der ihn Ende 2022 mit anderen Entwicklern entdeckt hat.

Der Angriff ist insgesamt ziemlich kompliziert. Im einfachsten Modell sind drei Knoten beteiligt: Der Sender A, der Zwischenmann B und der Empfänger C. Dabei kooperieren A und C, um B zu betrügen.

Um den Angriff zu verstehen, muss man ein paar Grundlagen zu Lightning kennen. Diese werde ich in den folgenden, grau unterlegten Absätzen vorstellen. Wer schon tief in der Materie drin ist, kann sie überspringen.

Um Zahlungen weiterleiten zu können, braucht unser Routing-Knoten B Payment-Channels mit A wie auch C. Wenn er eine Zahlung weiterleitet, steigt sein Guthaben im Channel zum Sender A, während es im Channel zu Empfänger B sinkt. Ein wenig wie eine Wasserleitung oder ein Ringtausch.

Jeder Payment-Zahlung ist ein „HTLC“. Das steht für „Hash Time Locked Contract“. Ein HTLC erlaubt es, die beteiligten Payment-Channels durch zwei Verfahren zu aktualisieren oder zu schließen: entweder indem man ein Geheimnis einfügt (das „Preimage“ eines Hash), oder indem eine gewisse Zeit verstreicht („Timelock“).

Lightning-Zahlungen folgen einem bestimmten, vom Protokoll genau definierten Drehbuch: A gibt B eine Transaktion, die den Channel zwischen den beiden aktualisiert, aber erst gültig ist, wenn B das Preimage einfügt. Dieses sendet A jedoch nicht direkt an B, sondern an C, der es B erst gibt, wenn dieser ihn bezahlt hat. Der Zwischenknoten B streckt also Geld vor, erhält aber im selben Moment die Information, die er braucht, um es sich von A zu holen.

Die Timelock ist eine Art Notausgang: Wenn C sich weigert, das Preimage herauszurücken, kann B nach Ablauf einer gewissen Zeit den Channel zu C mit der alten Balance schließen. Die Zahlung scheitert zwar, aber niemand hat Geld verloren.

Dabei ist wichtig, dass die Timelocks in der umgekehrten Reihenfolge der Zahlungsroute zuschnappen. Sie muss im Channel von B zu C früher eintreten als im Channel von A zu B. Das Lightning-Protokoll setzt daher eine Differenz von mindestens 34 Blöcken voraus.

Transaktionen aus dem Mempool löschen

Der Angriff, den Antoine Riard nun enthüllt, manipuliert mit ungheurem Aufwand den zeitlichen Ablauf der Timelocks, mit dem die HTLCs schließen. Er erlaubt es, dass A das Timelock vor B nutzen kann.

Zunächst läuft aber alles nach Plan: A sendet eine Zahlung an C, und der arglose Zwischenknoten B erfüllt seine Aufgabe. Er aktualisiert den Channel zu C und leitet damit die Zahlung weiter. Doch C weigert sich an dieser Stelle, das Preimage herauszurücken.

B ist nun nicht in der Lage, sich das Geld zu holen, das A ihm schuldet. Aber noch ist alles in Ordnung. B wartet darauf, dass die Timelock greift und reicht eine Onchain-Transaktion ein, die den Channel zu C mit dem Guthaben vor der letzten Lightning-Transaktion schließt. Er aktiviert also das Notfall-Protokoll, das die Guthaben zurücksetzt.

Doch C hat sich genau darauf vorbereitet. Er startet die „Transaction Replacement Cycling Attack“. Dies ist eine sehr ausgeklügelte Methode, um Transaktionen aus dem Mempool der unbestätigten Transaktionen zu löschen.

Ein Teil der Operation ist relativ einfach: C reicht eine Transaktion ein, die das Preimage nutzt, um den Channel mit B zu schließen. Da sie höhere Gebühren bezahlt, verdrängt sie die Timelock-Transaktion von C, die nun aus dem Mempool gelöscht wird.

B könnte nun allerdings das Preimage nutzen, um den Channel zu A ordnungsgemäß zu schließen. Daher hat C den Angriff so vorbereitet, dass er sofort danach auch die eigene Preimage-Transaktion aus dem Mempool löscht. Konkret hat er zwei Transaktionen in den Mempool gebracht, von denen eine die Outputs der anderen ausgibt.

Mit seiner Preimage-Transaktion schließt C nicht nur den Payment-Channel, sondern gibt auch einen Output der Eltern-Transaktion aus. Damit knüpft er die Gültigkeit dieser Transaktion an eine weitere Bedingung: den Output der Eltern-Transaktion. Wenn er diesen nun selbst ungültig macht, wird auch die Preimage-Transaktion ungültig. Also sendet er noch eine Transaktion ab, die denselben Output ausgibt wie die Eltern-Transaktion, aber sie durch höhere Gebühren aussticht.

Das Ergebnis der Aktion ist: Der Angreifer hat die Timelock-Transaktion von B im Mempool durch eine Preimage-Transaktion ersetzt, und diese im selben Zug durch eine weitere Transaktion verdrängt. So als wäre keine der beiden Transaktionen jemals geschehen.

Runde für Runde bis die Timelock greift

Unser Knoten B wird nun verzweifelt versuchen, die Rettungstransaktion wieder und wieder abzusenden, in der Regel einmal je Block. Doch C kann sein perfides Spiel immer wieder wiederholen. Er blockiert die Rettungstransaktion von B solange, bis die Timelock von A einsetzt. An der Stelle schnappt die Falle zu.

A macht sofort von seinem Timeout Gebrauch. Er schließt den Channel zu B mit der Rettungs-Transaktion. Er setzt also das Guthaben auf den Stand vor der letzten Lightning-Transaktion zurück. Sobald das geschehen ist, veröffentlicht C die Preimage-Transaktion – die echte, nicht die manipulierte – und sichert sich die Zahlung. B kennt danach zwar das Preimage, doch es bringt ihm nichts mehr, da der Channel mit A bereits onchain geschlossen wurde.

B fiel, anders gesagt, einem Double Spend zum Opfer. Er hat Geld an C vorgestreckt, es aber nicht von A erhalten.

Gegenmaßnahmen

Bisher gibt es unser Opfer B nicht. Der Angriff ist rein theoretisch: Er wurde im Live-Netzwerk bisher nicht beobachtet. Darüber hinaus wurde er mittlerweile deutlich schwieriger. Denn alle Lighning-Clients haben diverse Maßnahmen ergriffen, um ihn abzuwehren.

So versuchen die Clients nun, häufiger und in zufälligen Intervallen ihre Timeout-Transaktion abzusenden. Dies macht es für den Angreifer schwieriger, die Rettungstransaktion zu unterdrücken, während er mehr Gebühren bezahlen muss, da sich die Anzahl der Zyklen erhöht.

Da ein Lightning-Client auch ein Bitcoin-Node ist, der die unbestätigten Transaktionen im Mempool hält, kann er sie auch beobachten. So versuchen einige Clients nun, die Transaktion des Angreifers abzufangen und das Preimage zu extrahieren. Wenn sie dieses haben, können sie die Zahlung, die ihnen laut Protokoll zusteht, einlösen. Der Angriff liefe also ins Leere.

Darüber hinaus erhöhen die Clients ihre Standardeinstellung für die Differenz des Timelocks zwischen den Channels. Bei Eclair beträgt er mittlerweile 144, bei LND 80. Ein Angreifer muss die Timeout-Transaktion nun länger blockieren, was eventuell mehr Gebühren kostet und dem angegriffenen Knoten mehr Chancen gibt, das Preimage abzufangen.

„Nicht mehr als PR-Statements“

Olaoluwa Osuntokun von Lightning Labs hält den Angriff daher für keine unmittelbare Gefahr. Damit er Angriff, muss der Angreifer „die Transaktionen aus dem globalen Mempool sehr präzise zu ersetzen.“

Wenn nur eine einzige ehrliche Partei das Preimage erkennt, ist der Angriff gescheitert, und der Verteidiger kann sogar noch Geld gewinnen. Darüber hinaus „muss so ein Angriff perfekt ausgeführt werden für Stunden, wenn nicht Tage.“ Der Angreifer muss die Gebühren exakt berechnen; sind sie zu tief, ersetzen sie die Transaktion nicht, sind sie zu hoch, kommt die Transaktion vorschnell in einen Block.“ Es sei ein „ziemlich brüchiger Angriff“ mit enormen Voraussetzungen.

Antoine betont dagegen, dass der vorgestellte Angriff nur ein möglicher einer neuen Klasse sei. „Replacement Cycling Angriffe“, also Angriffe, die es verhindern, Timelock-Transaktionen in einen Block zu bringen, dürfte es noch weitere geben. „Trotz der Maßnahmen, die ergriffen wurden, bin ich überzeugt, dass solche Replacement Cycling Attacks weiterhin möglich sind für kompetente Angreifer.“ Darüber hinaus ist zu befüchten, dass sie auch andere Protokolle und Anwendungen betreffen, etwa CoinJoin.

Ein substanzieller Fix, so Antoine weiter, müsse auf der „Bitcoin Base-Layer“ geschehen, also der Ebene von Bitcoin Core, etwa indem man Nodes in die Lage versetzt, sich besser an vergangene, gelöschte Transaktionen aus dem Mempool zu erinnern. Solche Änderungen brauchen jedoch viel Zeit, da sie oft mit Nachteilen einhergehen, im Falle des Mempools etwa mit den Risiken, neue DoS-Angriffe zu ermöglichen. Bis dahin „bringt diese neue Klasse von Replacement Cycling Attacks Lightning in eine sehr bedrohliche Position.“

Matt Corallo drückt dies schärfer aus. Die Maßnahmen, die die Clients ergriffen haben, seien „lächerlich“. Sie lösen das Problem nicht, und man könne sogar diskutieren, ob sie „nicht mehr als PR-Statements“ sind.

Etwas weniger pessimistisch meint der Entwickler Peter Todd, die Ursache liege darin, dass „wir daran scheitern, RBF zu benutzen.“ Die richtige Weise, vorsignierte Transaktionen zu verwenden, sei es, „verschiedene Transaktionen zu signieren, um jeden vernünftigen Bedarf abzudecken, um die Gebühren zu erhöhen.“ Wenn man 10 Transaktionen vorbereite, die die Gebühren jeweils verdoppeln, deckt man ein Spektrum bis zur 1000-fachen Gebühr ab. Dies würde es dem Angreifer unmöglich machen, den Zwischenknoten B daran zu hindern, seine Timeout-Transaktion durchzubringen. Dass der Angriff überhaupt zur Debatte steht, sei ein Fehler im Lightning-Protokoll.

Die Lage ist also längst nicht aussichtslos – bleibt aber spannend.

Über Christoph Bergmann (2695 Artikel)
Das Bitcoinblog wird von Bitcoin.de gesponsort, ist inhaltlich aber unabhängig und gibt die Meinung des Redakteurs Christoph Bergmann wieder ---

1 Kommentar zu Ein neuer Angriff auf Lightning ersetzt unbestätigte Transaktionen und schadet Routing-Nodes

  1. Je mehr Komplexität, desto mehr potenzielle Angriffsfläche, insbesondere wenn man eine ewige Abwärtskompatibilität erhalten möchte, die effektiv nicht aktualisierten Nodes nur etwas vorgaukelt, was gar nicht stimmt.

    Etwas weniger pessimistisch meint der Entwickler Peter Todd, die Ursache liege darin, dass „wir daran scheitern, RBF zu benutzen.“

    Ich war früher kein Fan von RBF, bin aber mittlerweile auch für Full-RBF bei Bitcoin, da man sich klar sein muss, dass keine Transaktion final ist, solange sie in keinem Block ist (im Extremfall mehrere Bestätigungen hat). Früher hat praktisch jeder Miner/Pool die vorcompilierte Version von Core verwendet und Transaktionen im Mempool wurden nicht ersetzt, egal was – es sei denn der Mempool ist überlaufen. Bei ausreichenden Fees konnte man also eine unbestätigte Transaktion guten Gewissens annehmen, wenn auch mit Restrisiko. Seit der zunehmenden Professionalisierung und Zentralisierung des Minings verwenden große Pools angepasste/optimierte Software um ihre Blöcke zu bauen (wie man kürzlich an einem ungültigen Block aufgrund falscher Reihenfolge gesehen hat), gibt es ein reales Risiko, dass diese bei Konflikten im Mempool auch jeweils diejenige Transaktion aufnehmen, die die höchste Fee bezahlt. Full-RBF ist also nur konsequent und man sollte in Wallets eine ganz klare Sprache dafür verwenden “vorgemerkt / unsicher”.

    Das betrifft potenziell alle dezentralisierten Chains ohne irgendwelchen zentralen Aufpasser, auch Monero. Der Unterschied bei Monero ist aber, dass sich professionelle Mining Skalierung nicht lohnt, da man dafür Hardware anschaffen muss und mit all den Minern konkurriert, die ohnehin schon ihre CPU(s) haben und womöglich noch “kostenlosen” Strom im Elternhaus / beim Arbeitgeber beziehen und wegen ein paar CPUs wird kaum jemand den Quellcode entsprechend verändern und kompilieren, um vielleicht irgendwann wenn er einen Block findet, ein paar Dollar mehr an Gebühren einzusacken weil sich im Mempool zufällig ein Double Spend ergeben würde.
    Klar wäre es mir auch lieber, wenn das dezentrale Pool Mining über p2pool nicht nur bei 5-10% rumdümpeln würde, welches dank Gupax auch eine idiotensichere GUI bietet, aber die meisten Miner setzen leider weiterhin auf zentralisierte Pools, obwohl diese Gebühren abzwacken.

    Die richtige Weise, vorsignierte Transaktionen zu verwenden, sei es, „verschiedene Transaktionen zu signieren, um jeden vernünftigen Bedarf abzudecken, um die Gebühren zu erhöhen.“ Wenn man 10 Transaktionen vorbereite, die die Gebühren jeweils verdoppeln, deckt man ein Spektrum bis zur 1000-fachen Gebühr ab. Dies würde es dem Angreifer unmöglich machen, den Zwischenknoten B daran zu hindern, seine Timeout-Transaktion durchzubringen. Dass der Angriff überhaupt zur Debatte steht, sei ein Fehler im Lightning-Protokoll.

    Da schießt der Peter imho übers Ziel hinaus, denn eine x1.000 Fee bedeutet bei heute üblichen $1 mal eben $1.000, was bereits die Kapazität der meisten Channels überschreiten dürfte. Selbst bei $100 wäre das Routing nur noch finanzstarken Akteuren vorbehalten, die auf nur entsprechend große Channels setzen und stets darauf achten, dass deren Liquidität zu keiner Seite die entsprechende Fee unterschreiten… Professionalisierung statt Dezentralisierung entsprechend wie sie beim ASIC Mining schon längst passiert ist.

    Dezentralisierung ist eben nicht binär, sondern stark subjektiv und sollte möglichst ein fortwährender Prozess sein, nach dem man strebt.

Kommentar verfassen

%d