Ich verstehe, dass, wenn der DAO-Vertrag eine Auszahlungsfunktion hat, die Geld an Vertrag X sendet, Vertrag X böswillig sein und die Fallback-Funktion verwenden kann, um die Auszahlungsfunktion erneut aufzurufen. Im Fall des DAO-Vertrags X war jedoch eine weitere Kopie des DAO, sodass dieses böswillige Verhalten nicht auftrat.
Wie genau war das rekursive Senden möglich?
Dies ist die problematische Codezeile in der withdrawRewardFor
Funktion:
if (!rewardAccount.payOut(_account, reward)) <-- reentrant exploit
throw;
paidOut[_account] += reward;
Die Auszahlung ruft die Empfängerfunktion auf payout
:
function payOut(address _recipient, uint _amount) returns (bool) {
..
if (_recipient.call.value(_amount)()) {
..
}
Wenn _recipient
es sich um einen Vertrag handelt, wird die Fallback-Funktion des Vertrags aufgerufen . Dieser Empfänger wiederum kann den TheDao-Vertrag erneut aufrufen. Da withdrawRewardFor
es nicht gegen Wiedereintritt geschützt war, wurde es wieder erlaubt. paidOut[_account] += reward;
Dies bedeutete eine kontinuierliche Auszahlung, bevor der Code mit und darüber hinaus fortgesetzt werden durfte .
Der Artikel More Ethereum Attacks: Race-To-Empty is the Real Deal , der eine Woche vor dem Angriff geschrieben wurde, enthält eine detailliertere Analyse dieser Art von Hacks und Lösungsvorschlägen.
Um Ihre Frage zu beantworten, müssen Sie zwischen Verträgen und Angeboten unterscheiden.
Das DAO ist ein Vertrag , der Regeln kodifiziert, um Mittel über Vorschläge verfügbar zu machen .
Ein Vorschlag kann ein Antrag auf Investition oder ein Antrag auf Abhebung Ihrer eigenen Mittel sein (dies wird als Split -Vorschlag bezeichnet). Wenn ein geteiltes Angebot genehmigt wird, ruft es die splitDAO-API auf, um ein untergeordnetes DAO (untergeordneten Vertrag) zu erstellen. Der Code dieses untergeordneten Vertrags ist tatsächlich identisch mit dem ursprünglichen DAO.
Die SplitDAO-Funktion überträgt die angeforderten Geldmittel an die untergeordnete DAO. Aber es ruft auch eine vom Vorschlag bereitgestellte Standardfunktion auf , angeblich um die übertragenen Gelder zu handhaben. Und diese Funktion wird direkt nach der Geldtransferoperation aufgerufen, aber bevor die Gelder vom Gesamtguthaben von DAO abgezogen werden und bevor das Benutzerguthaben auf Null gesetzt wird .
Der rekursive Exploit wurde in diese Standardfunktion eingebettet. Es rief einfach wieder splitDAO auf.
In Wirklichkeit hätte die Überweisung von Geldern, die Reduzierung des Gesamtguthabens und das Setzen des Benutzerguthabens auf Null eine atomare Operation sein sollen. Andere Methoden (Sperren, Mutexe) hätten auch implementiert werden können, um sicherzustellen, dass der gesamte Aufteilungsvorgang abgeschlossen ist, bevor ein externer, vom Benutzer bereitgestellter Code ausgeführt wird.
David Schwarz
split
Funktion, die ausgenutzt wurde.Ismael
eth