Signature Replay Attacks in Solidity: The Bug That Looks Correct

개요

Solidity 스마트 계약에서 발생하는 Signature Replay Attack은 암호학적으로는 올바르게 보이지만, 서명된 메시지가 충분히 구속되지 않아 공격자가 이전 서명을 무한히 재사용하여 이익을 얻는 취약점입니다.

주요 내용

* Signature Replay Attack의 기본 원리: 사용자 오프체인 메시지에 서명하고 이를 온체인에 제출하는 메타 트랜잭션, Permit 플로우 등에서 발생합니다. 계약은 서명으로부터 서명자를 복구하고 해당 주체의 권한으로 작동하지만, 서명 자체에 대한 재사용 방지 메커니즘이 없다면 공격자는 동일한 서명을 계속 사용할 수 있습니다.

* 취약점 유형:
* Version 1: Nonce 부재: 서명된 해시에 Nonce가 포함되지 않아 동일한 서명을 무한히 재사용할 수 있습니다. executeWithSig 함수에서 서명자 확인만 거치고 Nonce를 소비하지 않아 발생합니다.
* Version 2: Domain Separator 부재 (Cross-contract replay): Nonce는 존재하지만, 서명된 메시지에 체인 ID(chainId)나 계약 주소(address(this))가 포함되지 않아 다른 체인이나 다른 배포된 동일 계약에서도 서명이 유효하게 됩니다. EIP-712와 Domain Separator를 사용하여 해결할 수 있습니다.
* Version 3: Nonce 재설정 (Nonce reuse after state reset): Nonce가 존재하지만, 특정 관리자 함수 등을 통해 해당 주소의 Nonce가 이전 사용 값으로 재설정될 수 있습니다. Nonce는 일관되게 증가해야 하며 재설정되지 않아야 합니다.

* AI의 Signature Replay Attack 탐지 기여: LLM 기반 분석은 단순히 Nonce 매핑의 유무를 넘어, 서명이 재사용될 수 있는 경로, 체인 ID 및 계약 주소와의 구속 여부, Nonce 재설정 가능성 등 다양한 맥락적 요소를 추론하는 데 도움을 줍니다.

* 안전한 Signature Gating을 위한 점검 항목:
* 서명된 해시에 Nonce가 포함되고 사용 시 증가하는지 확인합니다.
* EIP-712를 통해 서명이 block.chainidaddress(this)에 구속되는지 확인합니다.
* 이전에 사용된 값으로 Nonce를 재설정하는 코드 경로가 없는지 확인합니다.
* 서명된 페이로드에 단일 사용을 보장하는 모든 필드(금액, 수신자, 마감일 등)가 포함되는지 확인합니다.
* 오래된 서명이 나중에 재사용되는 것을 방지하기 위한 마감일(deadline)이 있는지 확인합니다.

시사점

Signature Replay Attack은 암호학적 검증만으로는 발견하기 어렵고, 서명된 메시지의 컨텍스트와 생명주기에 대한 깊은 이해가 필요합니다. 따라서 스마트 계약 개발자는 서명 검증 시 Nonce, 체인 ID, 계약 주소, 그리고 마감일 등 다양한 요소를 종합적으로 고려하여 보안을 강화해야 합니다.

원문 읽기 →
원문을 불러오는 중...

댓글

GitHub Discussions