Mirror Protocol이 @FatMan에 의해 익스플로잇된 것으로 보고되었습니다. 이 블로그에 관련 내용이 잘 정리되어 있습니다. 이 짧은 글에서는 공격 트랜잭션을 활용하여 어떻게 이 일이 발생했는지 자세히 설명합니다.

면책 조항: 이 글은 공개된 트랜잭션과 Mirror 프로토콜 및 Terra 생태계에 대한 저희의 이해를 바탕으로 작성되었습니다. 부정확한 내용이 있을 경우 알려주시기 바랍니다. 이 블로그에 대한 모든 의견을 환영합니다.
1 공격
1.1 준비
이 트랜잭션은 공격을 준비하는 데 사용되었습니다.
1단계: 이 트랜잭션에서 공격자는 먼저 100,000 USTC를 락 컨트랙트에 전송했습니다. 이는 포지션을 여는 데 반드시 필요한 것은 아니지만, 공격에 있어 매우 중요한 과정입니다.

2단계: 그 후 공격자는 10 USTC를 담보로 예치하고 collateral_ratio를 2.5로 지정하여 포지션을 열었습니다.

short_params가 지정되어 있어 민트 컨트랙트가 발행된 mAsset(즉, mETH)을 매도하고 획득한 USTC를 포지션의 잠긴 금액에 추가합니다.
2.1단계: 트랜잭션을 단계별로 살펴보겠습니다. 먼저, open_position 함수가 호출되어 ID가 43186인 숏 포지션을 엽니다.

2.2단계: 선택적 short_params가 추가되었으므로, 컨트랙트는 먼저 0.001208 mETH를 발행(현재 ETH 가격 기준)한 후 mETH-UST Pair에서 스왑하여 매도합니다.

2.3단계: 0.001208 mETH는 4.06582 USTC로 스왑되며, 관련 수수료(예: 세금)를 제한 후 스왑된 USTC가 락 컨트랙트로 전송됩니다. 이는 열린 포지션이 일정 기간 이후에만 잠금 해제될 수 있기 때문입니다.

2.4단계: 그런 다음 lock_position_funds_hook이 호출됩니다. 이 함수에서 position_locked_amount는 current_balance를 조회하고 current_balance와 locked_funds를 비교하여 계산됩니다.

그러나 1단계에서 확인했듯이, 100,000 USTC가 락 컨트랙트에 직접 전송되었기 때문에 locked_amount는 4 USTC가 아닌 약 100,004 USTC가 됩니다.

2.5단계: 마지막으로, increase_short_token이 호출되어 sLP 토큰을 기록합니다.

여기까지, 공격자는 100,000 USTC를 락 컨트랙트에 직접 전송하고 10 USTC를 담보로 하여 포지션을 열었습니다. 해당 포지션의 잠긴 금액은 약 100,004 USTC이며 일정 기간 이후 잠금 해제될 수 있습니다. 공격자는 1,000에서 100,000 USTC를 전송하는 방식으로 이러한 종류의 포지션을 다수 열었습니다.

1.2. 공격
Mirror Protocol은 포지션 ID의 중복 여부를 확인하지 않습니다. 이 경우, 공격자는 하나의 포지션에서 잠긴 금액을 반복적으로 잠금 해제하기 위해 다수의 중복 포지션 ID를 입력할 수 있습니다.
트랜잭션이 바로 공격 트랜잭션입니다. 예를 들어, 포지션 ID 43186의 경우, 공격자는 437번 중복하여 입력했습니다.

원본 컨트랙트 코드가 중복 여부를 확인하지 않기 때문에, 약 43.7M(437 * 0.1M)USTC가 (이 단일 함수 호출에서) 잠금 해제되었습니다.

다른 포지션들도 동일한 메커니즘으로 잠금 해제되었습니다.
2. 버그 수정
이 취약점은 해당 커밋에서 수정되었습니다.

구체적으로, unlockable_positions는 잠금 해제할 포지션 ID를 포함하는 벡터입니다. 원본 코드에서는 unlockable_positions에 중복 ID가 있는지 확인하는 로직이 없었습니다. 패치된 코드에서는 포지션 ID의 중복 여부를 확인하는 검사가 추가되었습니다.
3. 결론
@FatMan 및 다른 커뮤니티 멤버들이 지적했듯이, 이 버그는 몇 달간 존재했으며 실제 환경에서 익스플로잇되었습니다. 우리는 이미 실제 환경에서 익스플로잇된 취약점을 조용히 패치하는 것은 바람직한 보안 관행이 아니라고 생각합니다. 또한, 주목받는 DeFi 프로젝트들은 앱의 상태를 적극적으로 모니터링하고 비정상적인 상황이 발생했을 때 경보를 받을 수 있는 게이트키퍼를 배포해야 한다고 생각합니다.



