codehawks-2023-07-codehawks-escrow-contract-m03

[M-03] Funds can be lost if any participant is blacklisted

보고서

Summary

블락리스트 기능이 있는 토큰을 이용하는 경우, 참여자 중 하나가 블락되면 토큰을 분배할 수 없다.

Keyword

blocklisting token, erc20, asset lock, dos

Vulnerability

이 프로젝트는 WETH, USDC, LINK, DAI 등의 토큰을 이용한다고 했다. 이 중 USDC 토큰은 토큰 자체에 블락리스트 기능이 있다. 이외에 많은 유명한 토큰들이 블락리스트 기능을 이용한다.

다음은 USDC 토큰 함수이다. notBlacklisted modifier로 인해 호출자 또는 토큰을 주고받는 이들이 블락된 경우 거래할 수 없다.

    function transferFrom(
        address from,
        address to,
        uint256 value
    )
        external
        override
        whenNotPaused
        notBlacklisted(msg.sender)
        notBlacklisted(from)
        notBlacklisted(to)
        returns (bool)
    {...}

Escrow에 예치된 토큰이 움직이는 시나리오는 두가지 있다.

  • confirmReceipt함수를 이용해 거래 성립. 구매자가 미리 컨트랙트에 예치해둔 토큰을 판매자에게 전송함.
  • 분쟁이 발생한 경우 중재자가 resolveDispute 함수를 호출해 분배. 중개자는 수수료를 받고 판매자, 구매자에게 토큰을 분배해준다.

confirmReceipt의 경우 판매자, 구매자 주소 중 하나라도 토큰의 블락리스트에 올랐다면 토큰을 옮길 수 없어 프로토콜이 정상적으로 작동하지 않는다. resolveDispute의 경우 중재자 주소까지 포함된다.

일반적으로 불법활동에 참여한 계정은 블락되고, 단순히 토네이도 캐시를 이용한 것으로 블락되기도 한다. 불만을 품은 참여자(판매/구매/중재자)가 토네이도 캐시 등을 이용해 의도적으로 자신을 블락리스트에 올려 자금 분배를 차단하는 시나리오도 충분히 가능하다.

Impact

참여자중 하나가 블락리스트에 오르면 토큰을 옮길 수 없어 자금이 영원히 잠기게 된다.

Mitigation

  • confirmReceiptresolveDispute 함수에서 바로 토큰을 옮기는 대신, 각 참여자가 가져갈 수 있는 토큰 양을 상태 변수에 저장해둔다. 이후 각자가 토큰을 인출해가면 블락된 참여자 외 나머지는 분배받을 수 있다.
  • 또는 블락된 유저가 출금할 수 없는 문제를 해결하기 위해 토큰을 분배할 주소를 재설정하는 기능을 제공한다.

Memo

불만을 품은 참여자가 토네이도 캐시 등을 이용해 의도적으로 자신을 블락리스트에 올려 DoS한다는 공격 시나리오 아이디어가 괜찮다.


tags: bughunting, codehawks, smart contract, solidity, blocklisting token, erc20, dos, asset lock, severity medium