0. レビュー
- Solanaエコシステムの保護 (1) — Hello Solana
- Solanaエコシステムの保護 (2) — プログラム間呼び出し
- Solanaエコシステムの保護 (3) — プログラムのアップグレード
1. 概要
前回のブログでは、プログラムのアップグレード方法について説明しました。この記事では、DeFi分野で最も一般的で基本的なセキュリティトピックの1つである、アクセス制御に関連する問題について紹介します。
2. 手順
Solanaでは、各プログラムはentrypoint!で定義された単一のentrypointをエクスポートします。Ethereumとは異なり、クライアントはエントリポイントとして定義された単一の関数(通常はprocess_instructionと呼ばれます)のみを呼び出すことができます。エントリポイント関数は3つのパラメータを受け取ります。これらは、スマートコントラクトのプログラムID、プログラムが操作するアカウント、および命令データです。命令データは、どの命令が呼び出されるかを指定します。以下の図は例を示しています。命令データをアンパックすることで、さまざまな命令(例: Lock, Unlock)が選択されます。したがって、エントリポイントから到達可能な命令はすべての人に公開されており、指定された命令データで実行できます。

3. アカウント検証
前述のとおり、プログラムは読み取りまたは書き込みに必要なアカウントを受け取ります。この設計には2つの問題があります。読み取られるアカウントについて、アカウントに格納されているデータが信頼できることをどのように保証するか。書き込まれるアカウントについて、特権ユーザーのみがアカウントへの書き込み命令を呼び出せることをどのように保証するか。以下に、アクセス制御の問題を説明します。すべてのテストコードはこちらで見つけることができます。
3.1 コードレビュー (PrivilegeOwner)


まず、DoorとConfigの2つの構造体を定義します。作成されたdoorを開くことができるのは、構造体doorで指定されたキーアカウント(17行目)のみです。ただし、システム状態がロックされている場合、ドアを開くことはできません。これは構造体Config(81行目)で指定されています。

前述のとおり、Configアカウントはドアを開けることができるかどうかを指定します。この場合、プログラムには1つのConfigアカウントのみが存在する必要があります。これを実現するために、PDAを使用してConfigのデータを格納します。Configアカウントを初期化した後、is_initialized属性をtrueに設定して、攻撃者によって再度初期化されないようにします(108行目〜110行目)。

命令Open()はドアを開くために使用されます。この命令は、開かれるドアアカウント、configアカウント、およびdoorを開こうとするownerアカウントを含むいくつかの ВАЖНОなアカウントを受け取ります。ドアがプログラムに属しており、構成が有効であることを保証するために、doorアカウントの所有者とconfigアカウントをチェックします(204行目〜205行目)。これにより、悪意のあるユーザーが偽のアカウントを提供することを防ぎます。これは最初の質問に答えます。読み取られるアカウントが信頼できることを保証するには、アカウントの所有者を確認する必要があります!この場合、doorアカウントの所有者のみがドアを開くことができることに注意してください。この場合、所有者アカウントがdoorの実際のownerであるかどうか、さらに重要なのは、命令が所有者によって承認されているかどうかを確認します(217行目〜219行目)。

関数validate_owner()では、まずこれらの2つのアカウントの公開鍵が同じであるかどうかを確認し、次に所有者の署名を確認します。これは2番目の質問に答えます。特権ユーザーのみがopen命令を呼び出すことができることを保証するために、アカウントの所有者と署名者を確認する必要があります。close命令はopenと同様であり、詳細はコードに記載されています。
プログラムをテストネットにデプロイしました。以下のリンクで見つけることができます。
https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet
すべてのテストトランザクションを以下に示します。このトランザクションの全体的なプロセスは、Allocate PDA()-> 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 攻撃トランザクション
所有者のチェックと署名者のチェックの重要性を示すために、2つの攻撃シナリオを例として使用します。
シナリオ1
1つ目は、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アカウントの所有者はプログラムでなければならないことを意味します。したがって、攻撃者はこのチェックをバイパスできません。

シナリオ2
2番目のシナリオは、ドアのロックが解除されているときに悪意のあるユーザーがドアを開けようとするシナリオです。

この場合、実際の所有者アカウントをプログラムに渡します(419行目)。そしてトランザクションを送信します。結果を以下に示します。

「Signature verification failed」と表示されます。これは、ドアを開くには実際の所有者がトランザクションに署名する必要があることを意味するため、2番目の攻撃も失敗します。
4. まとめ
Solanaでは、命令はクライアントまたは他のプログラムから提供されるさまざまなアカウントに基づいて指定されたロジックを実装します。したがって、アカウントの適切なチェックは非常に重要です。
この記事では、アカウントを適切にチェックする方法を紹介し、2つの攻撃シナリオを使用してこれらのチェックの重要性を説明しました。引き続きフォローしてください。さらに多くの記事を共有します。
このシリーズの他の記事を読む:
- 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などの著名な投資家から2回の資金調達で数千万米ドルを受け取っています。
公式ウェブサイト: https://blocksec.com/
公式Twitterアカウント: https://twitter.com/BlockSecTeam




