Web3 기본 언어(2): Move는 어떻게 플래시 론 재진입 공격을 피할 수 있을까?

국승증권연구소
2022-12-30 15:56:08
수집
“재진입”은 플래시 론을 구현하는 기초이지만, 목표 계약에 취약점이 있을 경우 공격자는 재진입 공격을 수행할 수 있습니다.

저자: 송가길 임학의, 국승증권연구소

이전 보고서는 바닥 언어의 특징을 바탕으로 Move와 Solidity(이더리움)의 장점과 특징을 비교했습니다. Web3의 기초 연구로서, 본 보고서는 가장 특징적인 응용인 플래시 론의 관점에서 이더리움과 Move가 각각 어떻게 플래시 론을 구현하는지, Move가 어떻게 플래시 론 공격을 회피하는지를 분석합니다.

이더리움 계약 간의 상호작용은 메시지 통신을 통해 상태 일관성을 달성하며, 재진입 및 동적 호출을 허용합니다. 이러한 특징은 플래시 론을 구현하는 데 기초가 됩니다. 이 과정에서 계약 간의 함수는 서로 호출할 수 있으며------호출 과정에서 제어권이 이전됩니다. 만약 DeFi 프로젝트 플랫폼 계약에 취약점이 있다면, 차익 거래자는 해당 계약의 악의적인 코드를 이용해 관련 함수를 호출하여 자산을 탈취할 수 있습니다------계약 간의 상태 동기화 정보 차이를 이용해 하나의 프로세스가 끝나기 전에 자산을 이중 지불(이더리움 자산은 단순히 값이 할당됨)하거나 반복적으로 함수를 실행(원래 허용되지 않아야 하는 논리)하여 탈취합니다.

재진입 공격의 전제는 공격자가 배포한 계약에 악의적인 코드가 존재하는 것이지만, 가장 핵심적인 요소는:

1) 이더리움 계약 호출 시 제어권이 이전되어 악의적인 계약에 주도권을 제공합니다;

2) 프로세스가 종료되기 전에 재진입(반복 호출)이 가능하여, 악의적인 계약이 취약점을 이용해 함수를 반복 호출하여 자산을 탈취할 수 있습니다(예: 한 번의 인출 프로세스가 끝나지 않은 상태에서 여러 번 인출);

3) 이더리움 계좌 자산이 수치 잔액 형태로 존재하기 때문에, 자산을 반복적으로 탈취(이중 지불)할 가능성이 있으며, 프로세스가 종료되기 전에 악의적인 계약이 관련 계좌 자산 잔액 수치를 수정하여 탈취할 수 있습니다.

Move는 플래시 론의 새로운 운영 프로세스를 제안했습니다------뜨거운 감자(hot-potato) 모델로, 본질적으로 재진입을 폐기합니다. "뜨거운 감자(hot-potato)" 모델은 key, store, copy 및 drop 기능이 없는 구조로, Move 프로그램이 거래 실행 중에 단 한 번만 사용하는 구조입니다. drop, key 또는 store 기능이 없기 때문에, 뜨거운 감자는 "파괴" 함수를 호출하여 프로세스를 종료해야 합니다------이름에서 알 수 있듯이, 이는 뜨거운 감자이며, 프로세스 중 어떤 처분도 "뜨거운 손"이므로, 파괴 함수에 맡겨져야만 종료됩니다. 구체적인 프로세스는 다음과 같습니다:

1) 플래시 론 스마트 계약이 작동할 때 "뜨거운 감자"의 영수증(receipt)을 생성합니다;

2) 차익 거래자가 플래시 론 계약에서 대출을 받을 때, 플래시 론 계약은 대출 자금과 하나의 뜨거운 감자 영수증(receipt)을 보냅니다;

3) 차익 거래자는 대출 자금을 이용해 차익 거래를 수행합니다;

4) 차익 거래자가 상환할 때, 상환 함수(repays)를 호출하여 자금과 영수증(receipt)을 상환 함수에 전달하고, 영수증은 상환 함수에 의해 수신된 후 파괴됩니다.

플래시 론이 완료되기 위한 전제는 마지막으로 올바른 상환과 프로세스 종료이며, 프로세스 종료 이전에 악의적인 계약이 이더리움 시스템에서 반복 호출을 통해 관련 자산 계좌 값을 수정하여 탈취할 수 있습니다. Move 시스템의 플래시 론 프로세스가 종료되기 위한 전제는 올바른 자금 반환 외에도 뜨거운 감자라는 자원을 일회성으로 회수하고 파괴하는 처리가 필요하며, 이는 플래시 론의 원자성을 보장합니다.

1: 핵심 관점

플래시 론은 이더리움 DeFi 생태계에서 가장 특징적인 응용으로, 그 기초는 이더리움에서 사용하는 Solidity 언어가 동적 호출과 재진입을 허용한다는 것입니다. 이러한 동적 호출은 스마트 계약의 개방성과 조합성의 중요한 표현이지만, 그로 인해 발생하는 제어권 이전과 계약 함수의 반복 호출은 상당한 보안 위험을 초래하며, 업계에서는 플래시 론을 이용한 취약한 DeFi 자금 풀 사건이 자주 발생하고 있습니다. Move 언어는 동적 호출과 재진입을 허용하지 않으며, "뜨거운 감자" 모델을 사용하여 플래시 론을 간단하게 구현하므로 이더리움과 같은 보안 문제를 완전히 피할 수 있습니다. 두 시스템의 생태 응용 작업 방식에는 명확한 차이가 있으며, 이러한 차이의 근본 원인은 Move의 바닥 언어의 특징입니다. 우리는 이전 보고서 《Web3 바닥 언어: Move가 Solidity의 어떤 부족함을 보완했는가?》에서 이미 자세히 설명했습니다. 본 보고서는 플래시 론 응용 관점에서 두 시스템의 구현 응용의 다른 방식을 비교합니다.

2: 이더리움 플래시 론의 기초: 동적 호출과 재진입

플래시 론(Flash Loan)은 원주율 DeFi의 새로운 제품으로, 초고속 대출로 이해할 수 있습니다. 사용자는 동일한 거래(블록) 내에서 대출, 차익 거래, 상환 및 수수료 지급을 완료하기만 하면 되며, 원자 거래이기 때문에 대출자는 어떤 자산도 담보로 제공하지 않고 대출을 받을 수 있으며, 무자본 차익 거래 솔루션을 제공합니다.

우리는 이전 보고서 《Web3 바닥 언어: Move가 Solidity의 어떤 부족함을 보완했는가?》에서 언급했습니다:

"모듈화 및 계약 조합성 측면에서, Solidity(예: 이더리움) 위의 계약은 라이브러리(정적 라이브러리와 유사)를 통해 메시지를 전달하여 계약 간의 호출 및 상호작용을 실현합니다. 반면 Move 언어는 모듈(module)과 스크립트(script) 설계를 사용하며, 전자는 계약과 유사하고, Move 언어의 계약 조합성은 모듈 간의 조합을 통해 자원을 전달하는 방식으로 이루어집니다(즉, 앞서 언급한 자원). 조합성 측면에서 Solidity와 Move의 차이는 매우 뚜렷합니다."

이더리움 계약 간의 상호작용은 메시지 통신을 통해 상태 일관성을 달성하며, 재진입 및 동적 호출을 허용합니다. 즉, 계약 간의 함수는 서로 호출할 수 있으며------호출 과정에서 제어권이 이전됩니다. 이러한 특징은 플래시 론을 구현하는 데 기초가 됩니다.

구체적으로, 이더리움 거래 내에서 송금 작업 및 기타 일련의 계약 작업을 수행할 수 있으며, 스마트 계약 내의 기능 함수를 호출하여 여러 복잡한 기능을 실행할 수 있습니다------즉, 이더리움 기반 거래는 대출, 차익 거래, 상환 등 일련의 거래 작업을 통합할 수 있습니다.

플래시 론의 모든 작업은 하나의 블록 시간 내에 완료되며, 현재 이더리움의 블록 생성 속도는 Merge 이후 약 12초입니다------핵심은 12초가 아니라, 이 일련의 거래가 최종적으로 수익을 내고 상환되어야 한다는 것입니다. 만약 이를 달성하지 못하면, 이 거래는 블록에 패킹되지 않으며, 대출자에게 대출 및 차익 거래(실패) 작업은 유효 거래가 아닌 임시 상태에 불과합니다------즉, 원자 거래입니다. 따라서 사용자는 프로그래밍을 통해 실행해야 할 모든 단계를 스마트 계약 거래로 형성하고 대출, 사용 및 상환의 세 가지 단계를 완료해야 합니다.

위의 복잡한 거래 작업은 여러 계약 간의 동적 호출을 통해 구현되며, 이러한 호출은 재진입이 가능합니다(즉, 반복 호출이 가능합니다).

현재 사용자는 FURUCOMBO와 같은 제3자 프로젝트를 통해 플래시 론을 보다 간편하게 플러그인 방식으로 프로그래밍할 수 있으며, 실제로 코드를 작성하지 않고도 스마트 계약을 설계하여 플래시 론에 필요한 전체 작업을 최종적으로 수행할 수 있습니다. 구체적인 차익 거래 프로세스는 아래 그림과 같습니다(이용한 FURUCOMBO 플랫폼의 구체적인 환율은 예시입니다). 현재 Kyberswap 플랫폼의 가격 상황은 1 sUSD = 0.9927 DAI이며, Uniswap에서 1 DAI = 1.2411 sUSD입니다. 사용자는 이 두 플랫폼의 DAI-sUSD 거래 쌍 가격에 상당한 차익 거래 공간이 존재함을 발견하고, FURUCOMBO의 인터페이스를 통해 차익 거래 과정을 설계할 수 있습니다.

포함된 내용: 1. AAVE 대출 플랫폼의 플래시 론 기능을 통해 100 DAI를 대출받습니다; 2. Uniswap을 통해 100 DAI를 약 122개의 sUSD 토큰으로 교환합니다; 3. Kyberswap 플랫폼을 통해 sUSD 토큰을 약 122 DAI 토큰으로 교환합니다; 4. AAVE에서 대출받은 100 DAI 토큰과 수수료 0.09 DAI를 상환합니다; 5. 전체 플래시 론을 이용한 차익 거래 프로세스는 하나의 이더리움 거래 내에서 완료되며, 약 22 DAI의 수익을 얻습니다.

image

만약 이 이더리움 거래 내에서 대출된 자금이 상환되지 않는다면, 전체 대출 거래는 블록에 패킹되지 않으며, 대출이 실제로 발생하지 않은 것이므로 대출자의 자금은 어떤 영향을 받지 않습니다------중간의 대출 및 차익 거래 과정은 임시 상태일 뿐이며, 채굴자가 패킹하여 확인하지 않았습니다.

플래시 론의 특성과 시효 요구를 바탕으로, 현재 가장 널리 사용되는 응용은 차익 거래입니다. 차익 거래자는 자산을 사용하지 않고도 차익 거래 작업을 수행할 수 있으며, 플래시 론을 통해 필요한 자금량을 확보하여 차익 거래를 완료하고 대출 자금을 신속하게 상환할 수 있습니다. 이는 차익 거래자의 진입 장벽을 크게 낮추며, 이론적으로 누구나 차익 거래자가 될 수 있고, 무제한의 차익 자금을 이용해 작업을 수행할 수 있습니다.

위의 프로세스에서 볼 수 있듯이, 이더리움 계약의 제어권은 FURUCOMBO 플래시 계약-차익 거래자 계좌 계약-Uniswap 계약-Kyberswap 계약-플래시 론 계약 간에 전환되며, 동적 호출을 통해 관련 함수를 호출할 수 있습니다. 만약 DeFi 프로젝트 플랫폼 계약에 취약점이 있다면, 차익 거래자는 해당 계약의 악의적인 코드를 이용해 관련 함수를 호출하여 자산을 탈취할 수 있습니다------계약 간의 상태 동기화 정보 차이를 이용해 하나의 프로세스가 끝나기 전에 자산을 이중 지불(이더리움 자산은 단순히 값이 할당됨)하거나 반복적으로 함수를 실행(원래 허용되지 않아야 하는 논리)하여 탈취합니다.

Move 생태계에서는 자산이 단순한 값 할당이 아니며, 동적 호출과 재진입이 금지되어 있어 근본적으로 위험을 차단합니다. 그 구체적인 구현은 후에 설명하겠습니다.

3: Move와 Solidity의 플래시 론 구현에는 어떤 차이가 있나요?

3.1. 이더리움 플래시 론의 양날의 검: 동적 호출과 재진입성

구현 방식에서 이더리움 EVM(솔리디티 기반)은 동적 스케줄링을 가지고 있으며, 재진입을 통해 플래시 론을 구현할 수 있습니다. 우리는 이전 보고서 《Web3 바닥 언어: Move가 Solidity의 어떤 부족함을 보완했는가?》에서 언급했습니다:

"이더리움(솔리디티)의 자산은 해당 계약에 의해 제어되며, Token A 계약을 금고에 비유할 수 있습니다. 금고는 모든 사용자에게 수치 잔액을 할당하여 사용자가 보유한 Token A 자산 수량을 표현하지만, 자산 자체는 여전히 Token A 계약의 금고 내에 있습니다. 반면 Move 사용자 계좌는 사용자 자신이 제어하는 별도의 큰 금고이며, 모든 Token 자산은 이 금고 내에 보관됩니다. 이러한 Token은 수치 형태로 존재하지 않으며, 복사할 수 없고, 사용자에 의해 제어되는 자원(타입)입니다."

따라서 이더리움 EVM이 플래시 론 차익 거래를 구현하는 프로세스는 다음과 같습니다:

1) 사용자가 플래시 론 계약에 제어권을 넘깁니다;

2) 플래시 론 계약은 외부의 차익 거래 계약 프로그램 내의 실행 함수를 호출하여 요청된 대출 금액을 차익 거래 계약에 전송하고, 차익 거래 계약은 차익 거래 작업을 수행합니다;

3) 차익 거래 계약이 차익 거래를 완료하고 대출금을 플래시 론 계약에 반환하며, 실행 함수가 작업을 완료하고 제어권이 플래시 론 계약으로 돌아갑니다;

4) 플래시 론 계약은 상환 금액이 올바른지 확인하며, 올바르면 차익 거래가 성공하고, 그렇지 않으면 실패합니다.

위 과정에서 관련 함수는 동적 호출되며, 플래시 론 계약은 반환 금액이 올바른지 확인해야 종료되므로 제어권 이전 과정은 언제든지 발생할 수 있으며, 즉 재진입이 가능합니다------동시에 주의해야 할 점은 이더리움 계좌 자산이 수치 잔액 형태로 존재하기 때문에 재진입은 이중 지불의 가능성을 가져오며, 이는 취약점이 존재하는 부분입니다. 외부 계약 호출의 주요 위험 중 하나는 이들이 제어권을 장악할 수 있다는 것이며, 이러한 외부 계약 프로그램에 취약점이 있을 경우 공격자는 반복 호출을 통해 공격을 수행할 수 있습니다. 즉, 재진입 공격이 가능합니다.

image

재진입 공격은 이더리움 역사상 가장 심각한 공격 중 하나를 초래했으며, 이는 이더리움의 분기를 직접적으로 초래했습니다. 즉, 2016년 6월 17일의 The DAO 붕괴 사건입니다. 해커는 계약을 배포하여 "투자자"로서 The DAO에 일부 ETH를 저장했습니다. 그런 다음 해커는 The DAO 계약 내의 withdraw 함수를 호출하여 The DAO 계약이 해커에게 출금을 하도록 했습니다. 해커 계약(fallback 함수)에는 악의적인 취약점이 존재하여------종료 로직이 없었기 때문에 The DAO는 출금을 완료하지 못했습니다(이때 The DAO는 해커가 출금을 받았고 자신의 계좌 잔액이 0이 되었다는 것을 알지 못했습니다)와 제어권을 되찾지 못했습니다. 해커는 withdraw 함수를 반복 호출하여 자신의 초기 예치 ETH 수량을 초과하여 출금을 받았습니다.

플래시 론 공격 사건에서 공격자는 종종 악의적인 계약을 통해 재진입 공격을 수행합니다. 예를 들어, 2022년 3월 16일, 해커는 플래시 론을 통해 대출을 받고, 대출 프로젝트 Hundred Finance의 취약점을 이용해 실시간 재진입 공격을 수행하여 최종적으로 약 2363 ETH를 획득했습니다. 구체적인 프로세스는 복잡하지 않으며, Hundred Finance는 송금 후 기록을 수행하기 때문에 해커는 플래시 론을 통해 대출을 받고, 공격 계약을 통해 Hundred Finance 대출 풀에 자금을 예치하여 담보 대출을 수행했습니다.

공격 계약이 배포한 onTokenTransfer 함수는 기록 전에 대출 함수를 반복 호출하여(재진입 공격) 하나의 담보 자산을 지속적으로 다른 대출 풀에서 대출받았습니다. 송금 후 기록을 수행하기 때문에, 기록 시(프로세스 종료) 해커는 이미 공격을 수행하고 수익을 얻었습니다. 공격의 핵심은: 프로세스가 종료되기 전에 공격자 계약이 반복적으로 관련 함수를 호출하여 자산을 탈취할 수 있다는 것입니다.

image

예를 들어, 공격자 계약이 A 은행(프로젝트 A 대출 풀)에 자산을 담보로 대출을 요청하고, A 은행은 기록 결산을 완료하기 전에 대출을 시작합니다. A 은행이 기록 결산 프로세스를 완료하는 것은 플래시 론 거래가 성공해야 함을 의미합니다(원자성), 이때 자산이 A에 입고되어 기록됩니다.

그러나 A 은행과 다른 은행 간의 정보가 동기화되지 않기 때문에(계약 함수 간의 상태가 동기화되지 않음), 공격자는 A 은행이 자산 입고 기록을 완료하기 전에(즉, 공격 계약의 대출 프로세스가 종료되지 않은 상태에서, 이때 플래시 론 작업 프로세스가 종료되지 않았으며, 계약 함수 호출이 계속될 수 있음) 해당 자산을 B, C 등 다른 은행에 담보로 대출을 요청하여(재진입) 프로세스가 종료되면 공격자는 이미 플래시 론 공격을 완료하고 수익을 얻습니다.

재진입 공격의 전제는 공격자가 배포한 계약에 악의적인 코드가 존재하는 것이지만, 가장 핵심적인 요소는:

1) 이더리움 계약 호출 시 제어권이 이전되어 악의적인 계약에 주도권을 제공합니다;

2) 프로세스가 종료되기 전에 재진입(반복 호출)이 가능하여, 악의적인 계약이 취약점을 이용해 함수를 반복 호출하여 자산을 탈취할 수 있습니다(예: 한 번의 인출 프로세스가 끝나지 않은 상태에서 여러 번 인출);

3) 이더리움 계좌 자산이 수치 잔액 형태로 존재하기 때문에, 자산을 반복적으로 탈취(이중 지불)할 가능성이 있으며, 프로세스가 종료되기 전에 악의적인 계약이 관련 계좌 자산 잔액 수치를 수정하여 탈취할 수 있습니다.

"재진입"은 플래시 론을 구현하는 기초이며, 그러나 목표 계약에 취약점이 있을 경우 공격자는 재진입 공격을 수행할 수 있습니다. 이는 이전 보고서에서 자세히 설명했습니다.

3.2. MOVE의 "뜨거운 감자": 재진입이 없는 플래시 론

Move 언어는 동적 호출과 재진입을 금지하여 근본적으로 재진입 공격을 차단합니다. 그러나 Move 시스템의 자산은 자원 유형으로, 대출이 발생하면 실제로 이전이 발생합니다. 플래시 론의 원활한 상환을 어떻게 보장할 수 있을까요?

Move는 플래시 론의 새로운 운영 프로세스를 제안했습니다------뜨거운 감자 모델로, 본질적으로 재진입을 폐기합니다. "뜨거운 감자(hot-potato)" 모델은 key, store, copy 및 drop 기능이 없는 구조로, Move 프로그램이 거래 실행 중에 단 한 번만 사용하는 구조입니다. drop, key 또는 store 기능이 없기 때문에, 뜨거운 감자는 "파괴" 함수를 호출하여 프로세스를 종료해야 합니다------이름에서 알 수 있듯이, 이는 뜨거운 감자이며, 프로세스 중 어떤 처분도 "뜨거운 손"이므로, 파괴 함수에 맡겨져야만 종료됩니다. 구체적인 프로세스는 다음과 같습니다:

1) 플래시 론 스마트 계약이 작동할 때 "뜨거운 감자"의 영수증(receipt)을 생성합니다;

2) 차익 거래자가 플래시 론 계약에서 대출을 받을 때, 플래시 론 계약은 대출 자금과 하나의 뜨거운 감자 영수증(receipt)을 보냅니다;

3) 차익 거래자는 대출 자금을 이용해 차익 거래를 수행합니다;

4) 차익 거래자가 상환할 때, 상환 함수(repays)를 호출하여 자금과 영수증(receipt)을 상환 함수에 전달하고, 영수증은 상환 함수에 의해 수신된 후 파괴됩니다.

우리는 이전 보고서에서 이미 분석했듯이, 계좌 자산과 영수증(receipt)은 모두 자원 유형이며, "복사할 수 없고, 버리거나 재사용할 수 없으며, 안전하게 저장하고 이전할 수 있습니다." 따라서 영수증(receipt)은 처리되어야 하며(단 한 번만 사용 가능), 이더리움처럼 계좌에 수치 할당 처리만으로는 안 됩니다.

따라서 뜨거운 감자 모델은 대출된 자산(자원 유형, 대출되면 실제로 이전됨)이 반드시 반환되어야 함을 보장합니다. 영수증(receipt)은 뜨거운 감자와 같으며, 이는 타이머와 같은 폭발 장치입니다(여기서 타이머는 플래시 론 차익 거래가 원자 거래로서의 "시간"을 의미하며, 특정 기간이 아닙니다). 자금과 폭발 장치는 함께 대출되며, 어느 한 쪽도 폭발 장치를 보관할 수 없으며, 반드시 원래 장소로 반환되어야 해체될 수 있습니다------그렇지 않으면 거래가 완료될 수 없으므로, 플래시 론 자금은 반드시 반환될 수 있습니다.

image

플래시 론이 완료되기 위한 전제는 마지막으로 올바른 상환과 프로세스 종료이며, 프로세스 종료 이전에 악의적인 계약이 이더리움 시스템에서 반복 호출을 통해 관련 자산 계좌 값을 수정하여 탈취할 수 있습니다. Move 시스템의 플래시 론 프로세스가 종료되기 위한 전제는 올바른 자금 반환 외에도 뜨거운 감자라는 자원을 일회성으로 회수하고 파괴하는 처리가 필요하며, 이는 플래시 론의 원자성을 보장합니다.

응용 관점에서 볼 때, Web3의 바닥 대표는 개방성과 재구성을 보장하는 기초 위에서 코드 보안성을 높여야 합니다. Web3에서 코드는 정보뿐만 아니라 자산 호출과도 직접적으로 관련되어 있으며, 사용자 자산의 안전을 보장하는 것이 가장 중요합니다. 그렇지 않으면 Web3는 어두운 숲이 될 것입니다. 이더리움의 생태계는 스마트 계약의 활력을 보여주었으며, 다음 시대는 이 기초 위에서 안전성과 규정 준수로 계속 진화할 것입니다. 이는 우리가 현재 Web3 바닥 언어의 진화를 주목하는 핵심 논리이며, 다음 혁신의 물결을孕고 있습니다.

체인캐처(ChainCatcher)는 독자들에게 블록체인을 이성적으로 바라보고, 리스크 인식을 실제로 향상시키며, 다양한 가상 토큰 발행 및 조작에 경계해야 함을 상기시킵니다. 사이트 내 모든 콘텐츠는 시장 정보나 관련 당사자의 의견일 뿐이며 어떠한 형태의 투자 조언도 제공하지 않습니다. 만약 사이트 내에서 민감한 정보를 발견하면 “신고하기”를 클릭하여 신속하게 처리할 것입니다.
체인캐처 혁신가들과 함께하는 Web3 세상 구축