Anatomy of an Oracle Attack (차익거래 공격 보고서)

EJ
Terra
Published in
11 min readJul 17, 2019

For our global audience: Terra’s oracle implementation has known weaknesses which we have been working hard to improve. Concerns until recently were mostly theoretical. On July 15th we witnessed an exploitation which earned an attacker substantial profit. The attacker manipulated Luna’s price on exchange Coinone, creating a window for profitable on-chain swaps between Terra and Luna. In the spirit of full transparency, we share an evidence-based anatomy of the attack and highlight the weaknesses that allowed it to materialize. Immediate action was taken by our validator community to make similar attacks significantly harder. We share a summary of current and upcoming solutions. Please join the discussion about the attack on Agora here, and discussion on making the oracle more robust here. We are grateful for the community’s continuous feedback and look forward to your suggestions towards making the Terra protocol stronger and more resilient.

2019년 7월 15일, terra1q9m7dahs2nrs4v4l83843k9hagxwl0ytqqc8fy 주소를 사용하는 공격자가 테라의 오라클을 조작해 온-체인 마켓에서 무위험 차익거래를 진행했습니다.

테라 팀에서는 공격 직후, 해당 공격자가 사용한 프로토콜의 취약점을 개선해 같은 공격이 다시 일어나지 않도록 조치했습니다.

공격자가 사용한 테라의 취약점들에 대해 테라 팀은 내부적으로 추가적인 개선안을 연구중에 있습니다. 이는 https://agora.terra.money/t/adjusting-swap-liquidity/74 에서 자세하게 확인하실 수 있습니다.

이번 리포트에서는 공격자가 얼마만큼의 수익을 얻었으며, 해당 공격이 어떻게 이루어졌고, 공격자가 이용한 테라의 취약점들에 대해서 설명드리도록 하겠습니다.

MsgSwap 분석을 통한 공격자의 부당 수익 계산

공격자는 21개의 MsgSwap(이하 Tx)을 실행했고, 이중 Luna to KRT Tx는 8개, KRT to Luna Tx는 13개입니다.

공격자가 실행한 21개의 트랜잭션을 각각의 buy/sell 쌍으로 묶어 6개의 buy/sell 그룹으로 나누어서 공격자가 실제로 어느정도의 차익을 얻었는지 알아보도록 하겠습니다.

그룹 1

첫 번째 트랜잭션 그룹은 10:46 부터 11:13까지 진행되었습니다.

총 5개의 Tx로 구성되고, 2개의 Luna to KRT Tx와 3개의 KRT to Luna Tx들로 구성됩니다.

공격자는 첫 두 Tx에서 70100개의 루나를 119,235,503 KRT로 스왑하고, 다음 3개의 Tx를 통해 119,200,000 KRT를 스왑해서 72,320.1648개의 루나를 획득합니다.

첫 번째 트랜잭션 그룹에서 공격자가 얻은 수익은 +35,503 KRT와 +2,220.1648 루나 입니다.

그룹 2

두 번째 트랜잭션 그룹은 11:54 부터 11:58까지 진행되었습니다.

총 2개의 Tx로 구성되고 이는 각각 Luna to KRT, KRT to Luna Tx로 구성됩니다.

공격자는 먼저 70,000개의 루나를 118,432,978 KRT 로 스왑하고, 다음 Tx를 통해 115,000,000 KRT를 69,620.40909개의 루나로 스왑합니다.

두 번째 트랜잭션 그룹에서 공격자가 얻은 수익은 +3,432,978 KRT와 -379.590914 루나 입니다.

그룹 3

세 번째 트랜잭션 그룹은 12:08 부터 12:13까지 진행되었습니다.

총 4개의 Tx로 구성되고, 이는 1개의 Luna to KRT Tx와 3개의 KRT to Luna Tx로 이루어집니다.

공격자는 이번 그룹에서는 이전 그룹들과 달리 과감하게 스왑량을 늘립니다.

첫 번째 Tx를 통해서 130,000개의 루나를 218,888,098.7KRT로 스왑하고, 이어지는 3개의 Tx를 통해서 222,300,000KRT를 스왑해 134441.493개의 루나를 얻습니다.

세 번째 그룹에서 공격자가 얻은 수익은 -3411901KRT와 +4441.493 루나 입니다.

그룹 4

네 번째 트랜잭션 그룹은 12:18 부터 12:24까지 진행되었습니다.

총 3개의 Tx로 구성되고, 이는 1개의 Luna to KRT Tx와 2개의 KRT to Luna Tx로 이루어집니다. 공격자는 첫 번째 Tx를 통해서 100,000개의 루나를 168,723,013.9KRT로 스왑하고,

이어지는 2개의 Tx를 통해서 168,500,000KRT를 101603.105개의 루나로 스왑합니다.

네 번째 그룹에서 공격자가 얻은 수익은 -223013.9KRT와 +1603.105105 루나입니다

그룹 5

다섯 번째 트랜잭션 그룹은 12:32 부터 12:40까지 진행되었습니다.

총 3개의 Tx로 구성되고, 이는 1개의 Luna to KRT Tx와 2개의 KRT to Luna Tx로 이루어집니다.

공격자는 첫 번째 Tx를 통해서 50,000개의 루나를 84,675,104.6KRT로 스왑하고, 이어지는 2개의 Tx를 통해서 84,800,000KRT를 50,561개의 루나로 스왑합니다.

다섯 번째 그룹에서 공격자가 얻은 수익은 -124,895KRT와 +561.397534 루나입니다.

그룹 6

여섯 번째 트랜잭션 그룹은 13:09 부터 13:40까지 진행되었습니다.

총 4개의 Tx로 구성되고, 이는 2개의 Luna to KRT Tx와 2개의 KRT to Luna Tx로 이루어집니다.

공격자는 첫 두 Tx를 통해서 20,000개의 루나를 33,907,730.4KRT로 스왑하고, 이어지는 2개의 Tx를 통해서 33,100,000KRT를 19100.1673개의 루나로 스왑합니다.

마지막 그룹인 여섯 번째 그룹에서 공격자가 얻은 수익은 +807,730.4KRT와 -899.832709 루나입니다.

공격자가 얻은 수익

위 여섯 buy/sell 그룹을 통해서 공격자가 얻는 수익은 다음과 같습니다:

공격자는 실행한 6개의 트랜잭션 그룹중 5개에서 성공적으로 수익을 내었고, 마지막 트랜잭션 그룹에서는 손해를 봤습니다.

루나의 가격을 7월 16일 15:52분의 코인원 가격인 1725원으로 1 KRT를 1원으로 가정할 때,

공격자는 15일에 진행한 2시간 54분동안의 공격을 통해 총 13,980,549원의 수익을 얻은 것을 알 수 있습니다.

다음은 코인원 차트를 통해 공격자가 어떻게 공격을 진행하였는지 추측해 보도록 하겠습니다.

차트를 통한 공격 분석

호가창 스냅샷 데이터나, 매수/매도 거래 데이터가 있다면 공격자의 공격 방식에 대한 매우 유효한 분석을 낼 수 있지만,

안타깝게도 저희가 얻을 수 있는 정보는 코인원의 1분봉 데이터가 최선이었습니다.

따라서 코인원의 1분봉 데이터를 통해서 공격자가 어떤 방식으로 공격을 진행했는지 추즉해 보도록 하겠습니다.

스프레드 조작(9:22~11:06)

  • 9시 22분, 9시 35분, 9시 39분에 이루어진 시장가 매도로 인해서 1750~1700 사이의 스프레드가 발생합니다.
  • 이후 누군가가 1750~1700 사이를 매도 주문들로 채웠고, 또 누군가가 해당 매도 주문들을 시장가 매수를 통해서 없애버립니다.
  • 이후 호가(1750~1700)는 빈 상태로 유지되고, 이후 누군가가 11시 3분부터 6분까지 1700원~1615원의 호가를 지속적인 시장가 매도를 통해서 비우게 됩니다.
  • 이를 통해서 1750~1615원 사이의 빈 호가가 완성됩니다.

오라클 조작(10:57~13:40)

  • 공격자는 10시 57~59분 사이에 빈 호가에서 가장 위 호가에 소량의 루나를 계속 구매하는 것을 통해 해당 가격이 오라클 가격에 반영될 때 까지 기다린 것으로 보입니다. 이는 망치형 캔들과 굉장히 적은 거래량(약 10 루나)을 통해서 추측할 수 있는 부분입니다.
  • 공격자는 11시에 오라클 가격이 반영 되자마자 온체인에서 7만개의 루나를 KRT로 오라클 가격 1748(실제 온체인 스프레드 제거하면 약 1701)에 스왑합니다.
  • 이후 공격자는 1615원까지의 아래 호가를 시장가 매도를 통해서 없앱니다.
  • 이후 11시 6~9분 사이에 가장 아래 호가에 소량의 루나를 계속 구매하는 것을 통해 오라클 가격에 공격자가 조작한 가격이 반영되도록 합니다.
  • 시장 조작으로 오염된 오라클 가격이 11시 11분에 반영되는 순간, 공격자는 스왑을 통해서 KRT를 다시 루나로 바꿉니다. 이러한 과정을 반복해서 공격자는 차익거래를 완성합니다.

이를 통해서 공격자의 공격 과정은 다음과 같이 유추될 수 있습니다.

1.시장가 매수 매도를 통해서 호가창에 큰 스프레드 만들기

2.소량의 루나를 조작된 Best ask가격에 지속적으로 매수

3.오라클이 가장 최신의 가격을 불러오기 때문에, 해당 소량 매수를 통해서 오라클을 조작

4.오라클이 높은 가격으로 조작되면 루나를 테라로 스왑

5.이후 다시 루나를 조작된 Best bid 가격에 지속적으로 매도

6.오라클이 가장 최신의 가격을 불러오기 때문에, 해당 소량 매도를 통해서 오라클을 조작

7.오라클이 낮은 가격으로 조작되면 테라를 루나로 스왑

8. 2~7 반복

공격자의 2차 공격

추가적으로 테라 팀에서는 15일 오후 7시 경, 같은 방식의 공격이 다시 이루어지려는 것을 포착하고, 이를 유동성을 투입하여 호가 갭을 줄이는 방식으로 방어했습니다.

다행히도 빠른 대처 덕분에 해당 공격이 다시 일어나는 것은 막을 수 있었습니다.

공격의 원인이 된 취약점들

해당 차익거래가 이루어질 수 있었던 첫 번째 요인은, 먼저 세컨더리 마켓의 낮은 유동성입니다. 일반적으로 시장가 매수, 매도를 통해서 호가창의 스프레드를 조작하더라도, 이 조작된 스프레드가 오래 지속되는 것은 여렵습니다. 하지만 루나 세컨더리 마켓의 낮은 유동성은 조작된 스프레드가 일정 시간동안 유지되는 원인이 되었습니다.

두 번째는 온체인 오라클이 항상 최신 가격을 체인에 보냈다는 점입니다. 공격자는 이를 인지하고, 소량의 루나를 지속적으로 매수,매도해 원하는 가격이 오라클에 반영될 때 까지 기다렸습니다.

세 번째는 루나<>테라 테라<>루나 스왑이 반복되는 한, 온체인 스프레드 수수료가 지속적으로 증가하지 않는다는 점입니다.

온체인 스프레드 수수료는 선형적으로 증가하게끔 설계되었지만, 이는 루나<>테라 혹은 테라<>루나 스왑이 한방향으로 계속 발생할때만 선형적으로 증가합니다. 만약 공격자가 루나<>테라 테라<>루나 스왑을 반복한다면 스프레드 수수료는 일정 수준 이상으로 증가하지 않습니다. 따라서 공격자는 계속되는 스왑에도 일정 수준 이상의 수수료를 지불하지 않았습니다.

연구중인 개선안

테라 팀은 해당 공격을 떠나서, 온체인 마켓과 오라클의 추가적인 개선이 필요하다고 판단하고 내부적으로 다양한 개선안들을 연구중입니다.

저희는 테라의 온체인 마켓이 테라의 안정성을 유지하기 위한 시스템이라고 생각합니다. 따라서 루나의 가격 변동에 따라 공격받을 수 있는 현재의 온체인 마켓을 개선하려고 여러 연구들을 진행중에 있습니다.

대표적으로:

  1. 최신 시장가가 아닌 스프레드의 중간값을 오라클 가격으로 설정
  2. 짧은 이동 평균을 오라클에 적용
  3. 규모가 큰 스왑들에 대해서 온-체인 스프레드 수수료가 민감하게 반응하도록 조정

해당 주제들에 대한 연구가 완료되면, 테라 리서치 팀에서는 해당 주제들에 대한 리포트를 공유해드릴 예정입니다!

감사합니다!

--

--