
0. 복습
1. 개요
이전 블로그에서는 프로그램을 업그레이드하는 방법에 대해 논의했습니다. 이번 포스트에서는 DeFi 분야에서 가장 일반적이고 기본적인 보안 주제 중 하나인 접근 제어 관련 문제를 소개합니다.
2. 명령어(Instructions)
Solana에서 각 프로그램은 entrypoint!로 정의된 단일 entrypoint를 내보냅니다. Ethereum과 달리, 클라이언트는 일반적으로 process_instruction이라고 불리는 entrypoint로 정의된 단일 함수만 호출할 수 있습니다. entrypoint 함수는 세 가지 매개변수를 받습니다. 스마트 컨트랙트의 프로그램 ID, 프로그램이 작동할 계정, 그리고 명령어 데이터입니다. 명령어 데이터는 어떤 명령어가 호출될지를 지정합니다. 아래 그림은 예시를 보여줍니다. 명령어 데이터를 언패킹하여 다양한 명령어(예: Lock, Unlock)가 선택됩니다. 따라서 entrypoint에서 도달할 수 있는 명령어는 모든 사람에게 공개되어 있으며 지정된 명령어 데이터로 실행될 수 있습니다.

3. 계정 유효성 검사
앞서 언급했듯이, 프로그램은 읽거나 쓸 계정을 수신합니다. 이 설계에는 두 가지 문제가 발생합니다. 읽을 계정의 경우, 계정에 저장된 데이터가 신뢰할 수 있는지 어떻게 보장할 것인가. 쓸 계정의 경우, 권한 있는 사용자만 계정에 쓰는 명령어를 호출할 수 있는지 어떻게 보장할 것인가. 이하에서는 접근 제어 문제를 설명합니다. 모든 테스트 코드는 여기에서 찾을 수 있습니다.
3.1 코드 리뷰 (PrivilegeOwner)


먼저 두 가지 구조체인 Door와 Config를 정의합니다. 구조체 door에 지정된 key 계정(17번 줄)만 생성된 door를 열 수 있습니다. 그러나 구조체 Config(81번 줄)에 지정된 시스템 상태가 잠겨 있을 때는 문을 열 수 없습니다.

앞서 언급했듯이, Config 계정은 문을 열 수 있는지 여부를 지정합니다. 이 경우 프로그램에는 Config 계정이 하나만 있어야 합니다. 이를 달성하기 위해 PDA를 사용하여 Config의 데이터를 저장합니다. Config 계정을 초기화한 후, 공격자에 의해 다시 초기화될 수 없도록 is_initialized 속성을 true로 설정합니다(108번 줄 - 110번 줄).

명령어 Open()은 문을 여는 데 사용됩니다. 이 명령어는 열릴 door 계정, config 계정, 그리고 door를 열려는 owner 계정을 포함한 여러 계정을 수신합니다. 문이 프로그램에 속하고 구성이 유효한지 보장하기 위해, door 계정과 config 계정의 소유자를 확인합니다(204번 줄 - 205번 줄). 이는 악의적인 사용자가 가짜 계정을 제공하는 것을 방지합니다. 이것이 첫 번째 질문에 대한 답입니다. 읽을 계정이 신뢰할 수 있는지 보장하려면 계정의 소유자를 확인해야 합니다! door 계정의 소유자만 문을 열 수 있다는 점에 유의하세요. 이 경우, owner 계정이 door의 실제 owner인지, 그리고 더 중요하게는 명령어가 소유자에 의해 승인되었는지 확인합니다(217번 줄 - 219번 줄).

validate_owner() 함수에서, 먼저 두 계정의 공개 키가 동일한지 확인하고, 그 다음 소유자의 서명을 확인합니다. 이것이 두 번째 질문에 대한 답입니다. 권한 있는 사용자만 open 명령어를 호출할 수 있도록 보장하려면 계정의 소유자와 서명자를 확인해야 합니다. close 명령어는 open과 유사하며 세부 사항은 코드에서 확인할 수 있습니다.
프로그램을 테스트넷에 배포했으며 다음 링크에서 찾을 수 있습니다.
https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet
모든 테스트 트랜잭션은 아래에 나열되어 있습니다. 이 트랜잭션의 전체 과정은 AllocatePDA()-> InitializeDoor()-> InitializeConfig()-> Unlock() -> Open() -> Close()입니다.
https://explorer.solana.com/tx/2X9CyMrHTNEvbzXTE95gem2j8spnvsQsabFeSpV8hiNpYjiQPPzLRqt5KN86ZYRjnQvydvs7y5eUjJK7no8knDhk?cluster=testnet
https://explorer.solana.com/tx/2XfVWiXeQeHbpqAEYm3AH2RU6hunnqtr155EC4EAM5Bq9VVZNP6QocAav9cPjEQdJFcQrbsSSxiKadr4HPMov8pz?cluster=testnet
https://explorer.solana.com/tx/5Em41sg7yFXeNpnEJnhUQJanfLWKwjMqiBeNAqEEzFrSN9P8zKKafcv5F7RKT2pseB171qeoa8Uz4fKgazzayCnW?cluster=testnet
https://explorer.solana.com/tx/2PMtzpSgjnKDLGmRWBdUSFBPimWnudCPekUYbWzPzokENFYa4N4ab4HCtynfGrzswFPTgGYKHU8PccUMHv3mXHkR?cluster=testnet
https://explorer.solana.com/tx/3kviP9MqkWGMV4yA7k7yPQ5BGfXmcYLcctmY1u2D7n56eT1nx8jMtDumkUNJy8yA3KkmzrmfQLjqpigc8ehGZzBN?cluster=testnet
https://explorer.solana.com/tx/38iEaJBzuGMLbfcszdVB8pkniezH8JrA3XGq7JdADZTQ4hNQC82GSTUA2bmcypdVy3t7htWnUzkZ4F8EakmNvqz8?cluster=testnet
3.2 공격 트랜잭션
소유자 확인과 서명자 확인의 중요성을 보여주기 위해, 두 가지 공격 시나리오를 예시로 사용합니다.
첫 번째 시나리오
첫 번째는 config가 잠겨 있을 때 'door' 소유자가 문을 열려는 시도입니다. 이를 위해 다른 프로그램에서 가짜 config 계정을 생성하고, is_lock 속성에 false 값을 할당합니다. 커스텀 프로그램의 코드는 아래와 같습니다.
가짜 config 계정을 생성하기 위해 트랜잭션을 전송하며, 가짜 config 계정의 공개 키는 2MtSrbWp24VjPZQcSUkiWrvNro7qqKemVCsh3Yxc8LTy입니다.
https://explorer.solana.com/tx/2qSyrL5gdQXmgGCFzmzMm1StFQRkDgWpss9A9jV11q2fgDGM5C1XRuXvbX1N5Dt3q2pRqnmyXHVtXGF5dqadAzpJ?cluster=testnet
가짜 config 계정이 생성되면, 이를 프로그램에 입력합니다(423번 줄).

결과는 아래와 같으며, 로그에 incorrect program id for instruction이 출력되어 config 계정의 소유자가 반드시 프로그램이어야 함을 의미합니다. 따라서 공격자는 이 검사를 우회할 수 없습니다.

두 번째 시나리오
두 번째 시나리오는 악의적인 사용자가 문이 잠금 해제된 상태에서 문을 열려는 시도입니다.

이 경우, 실제 owner 계정을 프로그램에 입력하고(419번 줄) 트랜잭션을 전송합니다. 결과는 아래와 같습니다.

Signature verification failed가 출력되어, 실제 소유자가 문을 열기 위해 트랜잭션에 서명해야 함을 의미하므로 두 번째 공격도 실패합니다.
4. 요약
Solana에서 명령어는 클라이언트 또는 다른 프로그램이 제공하는 다양한 계정을 기반으로 지정된 로직을 구현합니다. 따라서 계정에 대한 적절한 확인이 매우 중요합니다.
이 글에서는 계정을 올바르게 확인하는 방법을 소개하고, 두 가지 공격 시나리오를 사용하여 이러한 확인의 중요성을 설명합니다. 계속 팔로우하시면 더 많은 글이 공유될 예정입니다.
이 시리즈의 다른 글 읽기:
- Solana 생태계 보안 (1) — Hello Solana
- Solana 생태계 보안 (2) — 프로그램 간 호출
- Solana 생태계 보안 (3) — 프로그램 업그레이드
- Solana 생태계 보안 (5) — 다중 서명
- Solana 생태계 보안 (6) — 다중 서명2
- Solana 생태계 보안 (7) — 타입 혼동
BlockSec 소개
BlockSec은 2021년 세계적으로 저명한 보안 전문가 그룹에 의해 설립된 선구적인 블록체인 보안 회사입니다. 이 회사는 대중적 채택을 촉진하기 위해 신흥 Web3 세계의 보안성과 사용성을 향상시키는 데 전념하고 있습니다. 이를 위해 BlockSec은 스마트 컨트랙트 및 EVM 체인 보안 감사 서비스, 보안 개발 및 위협을 선제적으로 차단하기 위한 Phalcon 플랫폼, 자금 추적 및 조사를 위한 MetaSleuth 플랫폼, 그리고 Web3 빌더들이 암호화폐 세계에서 효율적으로 탐색할 수 있는 MetaSuites 확장 프로그램을 제공합니다.
현재까지 이 회사는 MetaMask, Uniswap Foundation, Compound, Forta, PancakeSwap 등 300개 이상의 저명한 고객사에 서비스를 제공했으며, Matrix Partners, Vitalbridge Capital, Fenbushi Capital을 포함한 저명한 투자자들로부터 두 차례의 자금 조달 라운드에서 수천만 달러를 유치했습니다.
공식 웹사이트: https://blocksec.com/
공식 트위터 계정: https://twitter.com/BlockSecTeam




