code4rena-2022-11-blur-exchange-m02

[M-02] Hacked owner or malicious owner can immediately steal all assets on the platform

보고서

Summary

owner에 너무 많은 권한이 있고, 중앙화되어 있다. owner 계정으로 바로 컨트랙트를 업그레이드하여 토큰을 탈취할 수 있다.

Keyword

rug pull, centralization, ownable, approve, upgradeable, uups

Vulnerability

거래 토큰이나 NFT 거래를 정산하기 위해 유저들이 ExecutionDelegate 컨트랙트에 거래에 사용할 WETH나 NFT를 approve 해두고 이를 transferFrom으로 이동하는 구조로 구현되었다.

다음은 거래 대금 또는 NFT를 이동하는 Exchange._transferTo, _transferTo._executeTokenTransfer 함수이다.

function _transferTo(
    address paymentToken,
    address from,
    address to,
    uint256 amount
) internal {
    if (amount == 0) {
        return;
    }
    if (paymentToken == address(0)) {
        /* Transfer funds in ETH. */
        require(to != address(0), "Transfer to zero address");
        (bool success,) = payable(to).call{value: amount}("");
        require(success, "ETH transfer failed");
    } else if (paymentToken == POOL) {
        /* Transfer Pool funds. */
        bool success = IPool(POOL).transferFrom(from, to, amount);
        require(success, "Pool transfer failed");
    } else if (paymentToken == WETH) {
        /* Transfer funds in WETH. */
        executionDelegate.transferERC20(WETH, from, to, amount);
    } else {
        revert("Invalid payment token");
    }
}
 
function _executeTokenTransfer(
    address collection,
    address from,
    address to,
    uint256 tokenId,
    uint256 amount,
    AssetType assetType
) internal {
    /* Call execution delegate. */
    if (assetType == AssetType.ERC721) {
        executionDelegate.transferERC721(collection, from, to, tokenId);
    } else if (assetType == AssetType.ERC1155) {
        executionDelegate.transferERC1155(collection, from, to, tokenId, amount);
    }
}

문제는 Exchange 컨트랙트는 UUPS 이며, owner가 즉시 업그레이드 가능하다는 것이다. 이는 owner 계정을 신뢰해야만 하는, 굉장히 중앙화된 시스템이다. owner가 악의적이거나, PK가 유출되는 사고가 발생한다면 Exchange 컨트랙트를 마음대로 업그레이드하여 토큰을 탈취할 수 있다.

예를 들어 다음과 같은 함수를 추가하여 호출할 수 있다. 이를 통해 approve 해둔 모든 유저의 토큰을 탈취할 수 있다.

function _stealTokens(
    address token,
    address from,
    address to,
    uint256 tokenId,
    uint256 amount,
    AssetType assetType
) external onlyOwner {
    /* Call execution delegate. */
    if (assetType == AssetType.ERC721) {
        executionDelegate.transferERC721(token, from, to, tokenId);
    } else if (assetType == AssetType.ERC1155) {
        executionDelegate.transferERC1155(token, from, to, tokenId, amount);
    } else if (assetType == AssetType.ERC20) {
        executionDelegate.transferERC20(token, from, to, amount);
    }
}

Impact

owner가 악의적이거나, PK가 유출되는 사고가 발생한다면 즉시 플랫폼의 모든 자산을 훔칠 수 있다.

Mitigation

owner가 바로 업그레이드 하지 않고, timelock에 의해 업그레이드 하여 악성 행위가 발생했을 때 유저들이 이를 인지하고 apporval을 취소할 시간을 번다.

Memo

이 취약점은 동일한 프로젝트에 대해 2022.10에 열린 버그헌팅에서도 지적되었다. code4rena-2022-10-blur-exchange-m01 이미 지적된 건은 known issue로 처리된다고 되어있는데 그래도 제출하였다.. (시나리오만 약간 바꾼듯)

이 취약점을 제출한 warden은 중앙화와 관련된 문제는 유저들에게 경각심을 주기 위하여 항상 Medium으로 평가했으므로 이 취약점 역시 Medium으로 평가해야 한다고 주장했다. 중앙화 평가 사례 링크를 활용하자!


tags: bughunting, blur exchange, smart contract, solidity, nft marketplace, rug pull, ownable, centralization, uups, upgradeable, severity medium