Wenn mein Vertrag eine solche Auszahlungsfunktion hat
address bossAddress;
address employeeAddress;
uint256 bossSalary;
uint256 employeeSalary;
function payout (){
if (msg.sender==bossAddress){
employeeAddress.send(employeeSalary);
bossAddress.send(bossSalary);
selfdestruct(bossAddress);
}
}
Wenn ich ein bösartiger Chef wäre, hätte ich dann die Auszahlung so ausnutzen können, dass nur der Chef bezahlt wird?
A) Wenn die employeeAddress ein Vertrag ist, aber bossAddress eine reguläre Adresse ist, kann ich den Callstack-Angriff ausnutzen, sodass die Transaktion auf employeeAddress.send(employeeSalary) fehlschlägt, aber weiterhin bossAddress.send(bossSalary) ausgeführt wird? Ich denke, was ich frage, ist, ob beide Sendeaufrufe die Callstack-Anzahl reduzieren oder nur der Sendeaufruf, der eine Vertragsadresse beinhaltet.
B) Auf der anderen Seite, wenn die Mitarbeiteradresse ein Vertrag ist, der viel Benzin verbraucht, muss ich wahrscheinlich keinen Exploit machen, da die employeeAddress.send fehlschlägt, wenn kein Benzin mehr vorhanden ist, dann sollte der Chef bezahlt werden sowohl employeeSalary als auch bossSalary, dank des selfdestruct()-Aufrufs.
C) Und als letzten Punkt, gibt es eine Möglichkeit, Gas beim Sendeaufruf anzugeben? Dies sollte die meisten Out-of-Gas-Fehler verhindern, falls es sich bei employeeAddress tatsächlich um einen Vertrag handelt.
Ich muss nur überprüfen, ob mein Verständnis des Gas-/Callstack-Verhaltens korrekt ist.
A. Nein. Wenn die Anruftiefe bei 1024 liegt, employeeAddress.send
wird fehlschlagen. Die Tiefe bleibt bei 1024 und bossAddress.send
wird ebenfalls ausfallen. Die Tiefe wird nur auf 1023 verringert, wenn payout
(oder sein Aufrufer, je nachdem, wie payout
aufgerufen wird) fertig ist.
B. Ja, das klingt alles richtig und es besteht keine Notwendigkeit für eine Anruftiefenmanipulation.
C. Es gibt keine Möglichkeit, Gas für Solidity anzugeben, .send()
und es leitet Nullgas an den Empfänger weiter. Es liegt in der Verantwortung der Empfänger send()
, nichts/wenig in ihrer Fallback-Funktion zu tun, wenn sie Out-of-Gas vermeiden und Ether erhalten möchten.
Solidity send
leitet Nullgas weiter, sodass es nicht für einen Wiedereintrittsangriff verwendet werden kann.
Wenn der Vertrag mindestens das Doppelte hat bossSalary
(Beispiel: bossSalary
und employeeSalary
sind gleich) und der Boss zuerst mit bezahlt wird .call
, dann ist ein Reentrant-Angriff möglich:
function payout (){
if (msg.sender==bossAddress){
bossAddress.call.value(bossSalary)();
employeeAddress.call.value(employeeSalary)();
selfdestruct(bossAddress);
}
}
bossAddress
könnte eine Fallback-Funktion haben, die payout
ein zweites Mal aufgerufen wird, bevor der Mitarbeiter bezahlt wird. Da keiner der Rückgabewerte von .call
überprüft employeeAddress.call
wird, scheitert es aber nicht, throw
sodass der Chef beide Gehälter behalten darf.
Der Rückgabewert von allen .send
und .call
(und verwandten .callcode
, .delegatecall
) sollte sorgfältig geprüft und gehandhabt werden.
schiso
eth
if (!address.call.gas(0).value(...)(...)) throw;
sicherstellen, dass die Transaktion zurückgesetzt wird.Dennis Petersen
eth
send()
gesehen leitet 0 Gas weiter und das 2300 Gas ist ein Stipendium: letzter Punkt von github.com/ethereum/wiki/wiki/Subtleties )Dennis Petersen
eth
Giuseppe Bertone
address.call.gas(2300).value()()
schiso
eth
eth