Kadena 스마트 계약을 예로 들어 재진입 공격 및 교차 기능 공격을 피하는 방법을 간략하게 분석합니다.

이 게시물에서는 재진입과 교차 기능 재진입의 차이점과 Turing-incompleteness가 이러한 공격 중 일부를 어떻게 방지할 수 있는지 간략하게 설명합니다.
여기에서 우리는 Kadena 블록체인이 프로그래밍 언어인 Pact를 사용하지만 Turing 불완전성이 이러한 악의적인 악용이 발생하는 것을 막지 못하는 교차 기능 재진입 악용 사례를 제공할 것입니다.
이벤트 소개
Kadena 블록체인은 다른 L1 체인보다 높은 확장성, 보안 및 가용성을 달성하도록 설계되었습니다. 스마트 계약 작성을 위한 새로운 언어인 Pact를 개발했습니다.
이 언어는 사람이 읽을 수 있고 공식적으로 확인하기 쉬우며 보안 강화를 위해 Turing-incompleteness가 있습니다.
여기서 말하는 Turing-incompleteness는 Pact가 Turing-complete 프로그래밍 언어(Solidity나 Haskell과 같은)가 할 수 있는 일을 할 수 없다는 것을 의미합니다. 프로토콜에는 Turing 완전성이 거의 필요하지 않습니다.
튜링의 불완전성의 가장 중요한 점은 무한한 재귀가 없다는 것입니다. 이렇게 하면 공격 표면이 크게 줄어들지만 일부 "전통적인" 공격은 100% 피할 수 없으며 다음에 교차 기능 재진입 문제를 다룰 것입니다.
고전적인 재진입 공격
재진입 공격은 매우 일반적인 보안 문제입니다. 이 문제는 개발자가 찾기 어려울 뿐만 아니라 감사자가 발생할 수 있는 모든 잠재적 결과를 검토하기 어렵습니다.
재진입 공격은 함수가 외부 호출 전후에 특정 작업을 수행하는 순서에 따라 달라집니다.
계약이 신뢰할 수 없는 외부 계약을 호출하는 경우 공격자는 이 함수 호출을 계속해서 반복하여 재귀 호출을 형성할 수 있습니다. 그리고 다시 입력된 기능이 중요한 작업(예: 계정 잔액 업데이트)을 수행하면 비참한 결과를 초래할 수 있습니다.
아래는 단순화된 예입니다.
취약한 계약을 안전하지 않은 계약이라고 하고 악의적인 계약을 공격 계약이라고 합니다.
1. 공격자는 자금을 공격 계약으로 이전하기 위해 안전하지 않은 계약을 호출합니다.
2. 호출을 받은 후 안전하지 않은 계약은 먼저 공격자가 자금을 가지고 있는지 확인한 다음 공격 계약으로 자금을 이체합니다.
3. 자금을 받은 후 공격 계약은 폴백 기능을 실행하여 잔액을 업데이트하기 전에 안전하지 않은 계약을 다시 호출하여 프로세스를 다시 시작합니다.

이 공격은 무제한 재귀 호출을 통해 수행되기 때문에 언어가 튜링 완전하지 않으면 공격이 불가능합니다.
함수 간 재진입
교차 기능 재진입은 재진입 기능이 외부 호출을 수행하는 기능과 다른 기능을 갖는다는 점을 제외하면 고전적인 재진입 공격과 유사합니다. 이러한 종류의 재진입 공격은 일반적으로 감지하기 더 어렵습니다. 복잡한 프로토콜에는 가능한 모든 결과를 수동으로 테스트하기에는 가능한 조합이 너무 많기 때문입니다.
이것은 Pact 언어를 사용한 간단한 교차 기능 재진입 공격이라는 개념 증명으로 이어집니다.
Pact 모듈의 간단한 교차 기능 재진입
아래 코드 스니펫에서 볼 수 있듯이 계약의 함수는 특정 인터페이스를 구현하는 다른 계약을 외부에서 호출합니다. 이를 통해 잘 설계된 공격 계약에 재진입할 수 있습니다. Pact의 기능은 중요한 작업을 수행할 수 있는 사용자 권한을 부여하는 내장 기능입니다. 다음 코드는 예시용이며 실제 사례 계약에서 가져온 것이 아닙니다.
우리가 사용할 코드 예제는 세 부분으로 구성됩니다.
이미지 설명

주 계약이 악의적인 외부 모듈과 상호 작용하도록 하려면
이미지 설명

공격받은 시뮬레이션 예제 계약
첫째, 데이터베이스는 연관된 십진수와 함께 행에 문자열이 저장되는 테이블로 정의됩니다.
그런 다음 능력이 정의됩니다: CREDIT(이 예에서는 항상 참). 이 조건은 credit 기능에 필요하지만 with_capability 문의 bad_function에 의해 내부적으로만 부여됩니다. 즉, 크레딧을 직접 호출하는 데 실패합니다.
이제 credit 함수는 다음과 같이 정의됩니다. 입력으로 제공된 문자열에 잔액(소수점)을 추가합니다. 주소가 아직 테이블에 없는 경우에도 항목을 생성합니다.
마지막으로 bad_function 함수는 legit_address의 균형을 증가시킬 뿐만 아니라 입력 매개변수로 제공될 수 있는 이전에 정의된 인터페이스를 준수하는 계약에 대한 호출을 실행합니다.
get-balance 함수를 사용하면 이 테이블을 읽을 수 있습니다.
이미지 설명

메인 모듈에 다시 들어가 신용 기능을 호출합니다.
일반적인 프로세스는 다음과 같습니다.
a. 공격 계약을 매개변수로 사용하여 bad_function을 호출합니다.
b.CREDIT 기능 부여
c. "legit_address"의 잔액이 10 증가합니다.
d. 악성 모듈의 external_function 호출: 여전히 CREDIT 기능을 가지고 있기 때문에 계약을 다시 입력하고 신용 기능을 직접 호출할 수 있습니다."attacker_address "100의 균형.

그 후, (get-balance"legit_address")는 10을 반환합니다."attacker_address")는 100을 반환합니다.
재입국에 성공했습니다.
이제 credit을 재진입적으로 호출하는 대신 bad_function을 다시 재진입적으로 호출하면 어떻게 될까요? 첫 번째 credit 호출이 성공하더라도 재진입이 bad_function에 있기 때문에 재귀 호출이 되어 실행이 실패하게 됩니다.

마지막에 쓰기

마지막에 쓰기
무제한 재귀를 제거함으로써 Turing-incompleteness는 재진입 공격의 일부 벡터를 방지합니다.
그러나 교차 기능 재진입은 재귀 호출 없이 발생할 수 있으므로 Turing-incompleteness가 그러한 모든 공격 벡터를 방지하지 못하므로 사용자는 이 언어와 상호 작용할 때 재진입이 무해하다고 가정해서는 안 됩니다.
재진입 및 교차 기능 재진입은 매우 일반적인 보안 문제이며 Web3.0 분야에서도 일련의 대규모 공격이 발생했습니다.
Pact는 스마트 계약 프로그래밍 언어로서 큰 잠재력을 가지고 있습니다.
Solidity나 Haskell과 같은 다른 언어와는 다소 다른 접근 방식을 취합니다. Pact는 보안을 위해 Turing-incompleteness에만 의존하지 않습니다. 이 언어는 더 쉽게 읽고 이해하고 공식적으로 확인할 수 있도록 설계되었습니다.
그러나 프로그래밍 언어는 모든 공격 벡터에 영향을 받지 않습니다. 따라서 개발자는 사용 중인 언어의 고유한 기능을 이해하고 배포 전에 모든 프로젝트를 철저히 감사해야 합니다.
현재 CertiK의 감사 및 종단 간 솔루션은 현재 시장에 나와 있는 대부분의 생태계를 포괄하고 거의 모든 주류 프로그래밍 언어를 지원하며 체인은 보안 기술 지원을 제공합니다.


