GivingThanks

First Flight #28
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Invalid

Lack of Validation on Charity Address in GivingThanks Contract

Summary

The GivingThanks contract allows users to donate to any charity address, relying on the isVerified method from the CharityRegistry contract to verify if a charity is legitimate. However, the contract does not ensure that the charity address provided by the donor is valid and well-formed. This lack of validation opens up the possibility for users to interact with non-existent or invalid addresses (e.g., zero addresses, addresses without fallback functions, or incorrect charity contracts), potentially leading to loss of funds or unintended behaviors.

Location of Vulnerability:

The vulnerability is located in the donate function of the GivingThanks contract, specifically on Line 9:

require(registry.isVerified(charity), "Charity not verified");

While the charity address is checked for verification, there's no initial validation to ensure that the address is well-formed or properly set. A user could accidentally or intentionally pass in an invalid address (like 0x0000000000000000000000000000000000000000), resulting in a failed transaction without providing clear feedback on the issue.

Vulnerability Details

Problems:

  • Zero Address: A user could donate to the zero address (0x0000000000000000000000000000000000000000), which would be an invalid recipient for Ether or tokens. This could cause the funds to be lost without any clear indication of an error from the contract.

  • Untrusted Contract Addresses: There is no check to ensure that the charity address is a contract or that the contract is properly implemented to accept Ether. Users could send Ether to addresses that do not have any receive or fallback functions, which would cause the transaction to fail.

  • Potential for Mistyped or Invalid Addresses: If a user enters an incorrect charity address, the transaction will fail silently, without providing proper feedback to the user.

Exploit Scenario:

  1. Donation to Zero Address:
    A user might mistakenly or maliciously send a donation to the 0x0 address, causing the Ether to be lost without proper feedback. The user would not receive an error in the contract, and the funds would effectively be "burned."

  2. Donation to Invalid Contract:
    A user might donate to a contract address that is not capable of receiving Ether or handling the donation in the expected way. This could result in Ether being sent to an address where it cannot be used, causing a loss of funds.

  3. Unintended Behavior in Malicious Contracts:
    An attacker could provide a malicious contract address that appears to be a verified charity but performs harmful actions. While the isVerified check would pass, the contract itself may execute unintended or malicious behavior.

Consequences:

  • Loss of Funds: Ether could be sent to the zero address or a contract that cannot handle it, resulting in a loss of funds for the donor.

  • Untrusted Interactions: The contract does not validate whether the charity is a trustworthy or legitimate address beyond verification, which could lead to the donation being misdirected or misused by malicious actors.

  • User Confusion: If a user donates to an invalid address, the transaction may fail without clear error messages, leading to confusion and potential user dissatisfaction.

Root Cause:

The contract relies entirely on the isVerified function from the CharityRegistry contract for validation, but it does not perform basic checks to ensure the charity address is a valid Ethereum address. It assumes that the charity address is always valid and functional without further verification.

Impact

  • Loss of Funds: Donors may inadvertently lose funds by sending Ether to invalid addresses.

  • Donation Confusion: Donors may be confused when their donation seems to go through, but nothing happens.

  • Potential Abuse: Malicious actors could exploit the lack of validation to trick users into donating to harmful or untrusted contracts.


Tools Used

  • Slither: Used for static analysis to check for any unsafe address handling or missing validations.

  • MyEtherWallet: To interact with the smart contract and simulate sending donations to invalid addresses.

  • Foundry: For test-driven exploration and exploiting the vulnerability by simulating donations to malicious or invalid addresses.


Recommendations

To fix this vulnerability, consider the following measures:

1. Validate Charity Address Before Sending Funds

Before calling the isVerified function, add a check to ensure the charity address is not a zero address and that it is a valid address that can accept Ether.

  • Zero Address Check:

    require(charity != address(0), "Invalid charity address: zero address");
  • Ensure Charity is a Contract:
    Add a check to ensure the charity address is a contract (i.e., has code), not just an externally owned account (EOA). This can be done by checking if the code size at the charity address is greater than 0.

    Example:

    require(isContract(charity), "Charity address is not a contract");
    // Helper function to check if an address is a contract
    function isContract(address account) internal view returns (bool) {
    uint256 size;
    assembly { size := extcodesize(account) }
    return size > 0;
    }

2. Provide Clearer Error Messages

Ensure that any failed donation provides clear feedback to the user about why the donation failed, including the possibility of sending Ether to an invalid address.

3. Implement Donation Confirmation Mechanism

Consider adding an event or receipt system to confirm the donation and ensure the donor is aware that the funds have been sent to a valid and functioning charity address.


Proof of Concept for Lack of Charity Address Validation

Overview:

The vulnerability allows users to send donations to invalid or untrusted addresses due to a lack of validation of the charity address. This leads to potential loss of funds or interaction with malicious contracts.

Actors:

  • Attacker: An attacker could provide an invalid address (such as the zero address or a malicious contract) for the charity donation.

  • Victim: The victim is the donor who mistakenly sends Ether to an invalid address.

  • Protocol: The GivingThanks contract.

Working Test Case:

  1. Donation to Zero Address:

    contract TestGivingThanks {
    GivingThanks givingThanks;
    function setUp() public {
    givingThanks = new GivingThanks(address(this)); // Deployed contract
    }
    function testDonateToZeroAddress() public {
    address zeroAddress = address(0);
    // Donor sends Ether to the zero address
    vm.prank(msg.sender);
    givingThanks.donate{value: 1 ether}(zeroAddress); // Transaction fails silently
    }
    }
  2. Donation to Invalid Charity Contract:

    contract InvalidCharity {
    // Empty contract, cannot accept Ether
    }
    contract TestGivingThanks {
    GivingThanks givingThanks;
    InvalidCharity invalidCharity;
    function setUp() public {
    givingThanks = new GivingThanks(address(this)); // Deployed contract
    invalidCharity = new InvalidCharity();
    }
    function testDonateToInvalidCharity() public {
    // Donor donates to a contract that cannot accept Ether
    vm.prank(msg.sender);
    givingThanks.donate{value: 1 ether}(address(invalidCharity));
    // No funds received, user may not be notified
    }
    }

Conclusion:

The lack of validation on the charity address in the GivingThanks contract is a medium-risk vulnerability. It could cause donations to be sent to invalid addresses (e.g., zero addresses or untrusted contracts), resulting in loss of funds or confusion for users. To mitigate this, basic address validation checks (zero address and contract checks) should be implemented to prevent these issues.

Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.