#39153 [SC-Insight] Unauthorized Token Creation and Minting Vulnerability

Submitted on Jan 23rd 2025 at 15:35:01 UTC by @kenzo for Audit Comp | Butter

  • Report ID: #39153

  • Report Type: Smart Contract

  • Report severity: Insight

  • Target: https://github.com/immunefi-team/audit-comp-butter-cfm-v1-playmoney

  • Impacts:

    • Protocol insolvency

    • Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)

Description

Brief/Intro

The PlayCollateralTokenFactory contract contains a critical vulnerability in its createCollateralToken function that allows any user to create tokens with arbitrary supply and gain full control over token transfers. This bypasses the intended restrictive nature of the token contract where only specific addresses should be able to send/receive tokens.

Vulnerability Details

The vulnerability exists in the createCollateralToken function of the PlayCollateralTokenFactory contract:

function createCollateralToken(
    string memory name, 
    string memory symbol, 
    uint256 initialSupply, 
    address owner
) external returns (address) {
    PlayCollateralToken newToken = new PlayCollateralToken(
        name, 
        symbol, 
        initialSupply,
        CONDITIONAL_TOKENS, 
        owner
    );
    
    emit PlayCollateralTokenCreated(address(newToken));
    return address(newToken);
}

The vulnerability arises because:

  1. Any address can call createCollateralToken

  2. The caller can specify any amount for initialSupply

  3. The caller can make themselves the owner

  4. As owner, they gain full control over token transfers

Attack scenario:

  1. Attacker calls createCollateralToken with themselves as owner

  2. Attacker creates massive supply of tokens

  3. Being the owner, attacker can now transfer tokens to any address

  4. This bypasses the intended restriction where only owner or ConditionalTokens should control transfers.

Impact Details

As stated in PlayCollateralToken.sol, this is a restrictive ERC20 for "play money": only the owner or ConditionalTokens can send or receive tokens. However, due to this vulnerability:

  1. Any address can create new tokens with themselves as owner

  2. They can mint arbitrary amounts of tokens

  3. As owner, they gain full transfer rights, bypassing the intended restrictions

  4. This completely breaks the token's security model where transfers should be restricted

Recommendation

Add access control to the createCollateralToken function to ensure only authorized addresses can create new tokens.

Proof of Concept

Add this to PlayCollateralTokenFactoryTest.t.sol

function testUnauthorizedTokenCreation() public {
       address attacker = makeAddr("attacker");
       vm.startPrank(attacker);
       
       // Create token with massive supply for attacker
       uint256 massiveSupply = 1_000_000_000_000 ether;
       address tokenAddr = factory.createCollateralToken(
           "Token",
           "TKN",
           massiveSupply,
           attacker
       );

       PlayCollateralToken token = PlayCollateralToken(tokenAddr);

       // Verify attacker has full control
       assertEq(token.OWNER(), attacker, "Attacker should be owner");
       assertEq(token.balanceOf(attacker), massiveSupply, "Attacker should have all tokens");
       assertEq(token.totalSupply(), massiveSupply, "Total supply should be massive");

       vm.stopPrank();

       // Log the details
       emit log_named_address("Token creator & owner", attacker);
       emit log_named_address("Token address", tokenAddr);
       emit log_named_uint("Supply created", massiveSupply);
   }

Last updated

Was this helpful?