Web アプリ開発セキュリティ・ベストプラクティス

認証

監査済みの認証サービスとクライアントサイド IC ライブラリを使用する

セキュリティ上の懸念事項

Web アプリでユーザー認証や Canister コールを自分で実装するのは、エラーが起こりやすくリスクが高いです。例えば、Canister コールをゼロから実装した場合、署名の作成や検証に関するバグが発生する可能性があります。

推奨

  • 認証には Internet Identity などを使用し、Canister コールには agent-js、Dapp から Internet Identity と対話するには auth-client を使用することを考えてみてください。

  • もちろん、認証のために IC 上の代替認証フレームワークを検討することもオプションの一つです。

適切なセッションタイムアウトを設定する

セキュリティ上の懸念事項

現在、Internet Identity は有効期限付きの委任を発行しています。この有効期限は、 auth-client で設定することができます。委任の有効期限が切れると、ユーザーは再認証する必要があります。適切な値を設定することは、セキュリティとユーザビリティのトレードオフです。

推奨

OWASP Recommendations を参照してください。セキュリティに敏感なアプリケーションでは、30分のタイムアウトを設定する必要があります。

Note:アイドルタイムアウトは近々導入されるかもしれません。ここ を参照してください。

運用中の agent-js で fetchRootKey を使用しない

セキュリティ上の懸念事項

agent-jsagent.fetchRootKey() を使用すると、テスト環境において、ステータスコールからルートサブネット閾値公開鍵を取得することが可能です。この鍵は Canister のアップデートコールで受信した認証データの閾値署名を検証するために使用されます。この方法をプロダクション環境の Web アプリで使用すると、攻撃者は自分の公開鍵を提供することができ、アップデートレスポンスのすべての信頼性保証を無効にすることができます。

推奨

実運用環境では決して agent.fetchRootKey() を使用せず、テストビルドのときだけ使用します。このメソッドを呼び出さない場合、ハードコーディングされたメインネットのルートサブネット公開鍵が署名検証に使用されることになります。

Internet Computer に特有でなく一般的なベストプラクティス

このセクションのベストプラクティスは一般的なものであり、Internet Computer に特化したものではありません。このリストは決して完全なものではなく、過去に問題になった非常に具体的な懸念事項をいくつか挙げているに過ぎません。

フロントエンドで入力を検証する

セキュリティ上の懸念事項

信頼できない情報源(ユーザーなど)からのデータの入力検証を怠ると、不正なデータが保存され、ユーザーに配信される可能性があります。これは、DoS、インジェクション攻撃、フィッシングなどにつながる可能性があります。

推奨

  • Canister でのデータ検証に加え、フロントエンドでデータ検証を実施しましょう。データ検証はできるだけ早く行うべきです。

  • OWASP Input Validation Cheat Sheet を御覧ください。

信頼できないドメインから JavaScript(およびその他のアセット)を読み込まない

セキュリティ上の懸念事項

<canister-id>.ic0.app 以外のドメインから信頼されていない JavaScript を読み込むことは、そのドメインを完全に信頼することを意味します。また、これらのドメイン(<canister-id>.raw.ic0.app を含む)から読み込まれたアセットはアセット認証を使用しません。

もし、悪意のある JavaScript を配信した場合、LocalStorage から agent-js が管理する秘密鍵を読み取るなどして、Web アプリまたはアカウントを乗っ取ることができます。

信頼できないドメインから CSS などの他のアセットを読み込むことは、セキュリティリスクであることに注意してください。例えば、ここ を参照してください。

推奨

  • JavaScript やその他のアセットを他のオリジンから読み込むことは避けるべきです。特にセキュリティ上重要なアプリケーションでは、他のドメインが信頼できるものであると仮定することはできません。

  • ブラウザに配信されるすべてのコンテンツが、Canister によって提供され、アセット証明書を使用して証明されていることを確認します。これは、特に JavaScript、フォント、CSS などに対して当てはまります。

  • コンテンツセキュリティポリシー を使用して、他のオリジンからのスクリプトやその他のコンテンツがまったく読み込まれないようにします。コンテンツセキュリティポリシー(CSP)を含むセキュリティヘッダを定義する も参照してください。

コンテンツセキュリティポリシー(CSP)を含むセキュリティヘッダを定義する

セキュリティ上の懸念事項

セキュリティヘッダは多くのセキュリティに関する問題の対応に使用されます。例えば、クリックジャッキングからの防御、TLSの強制、信頼できないドメインからの JavaScript または他のコンテンツがブラウザで実行しないようにするなどです。これらのヘッダーを適切に設定しないと、明確なセキュリティ上の問題が発生し、多層防御が失われます。

推奨

暗号化:Web Crypto API を使って XSS からキーマテリアルを保護する

セキュリティ上の懸念事項

ブラウザのストレージ (sessionStoragelocalStorage など)に鍵を保存することは、これらの鍵に JavaScript コードがアクセスできるため、安全でないと考えられています。これは、XSS 攻撃や、他のドメインから信頼できないスクリプトを読み込むときに起こる可能性があります( 信頼できないドメインから JavaScript(およびその他のアセット)を読み込まない も参照して下さい)。

推奨

WebCrypto API を使用して、JavaScript からキーマテリアルを隠します。generateKeyextractable=false を使用します。これ を参照してください。この例は、People Parties プロジェクトで見ることができます。ここ を参照してください。これにより、JavaScript から秘密鍵にアクセスすることは不可能になります。

安全な Web フレームワークを使用する

セキュリティ上の懸念事項

最近の Web フレームワークは、Web ページに表示される潜在的なユーザー提供のデータを安全にエスケープ/サニタイズするため、XSS のような攻撃を非常に難しくしています。このようなフレームワークを使用しないことは、XSS のような攻撃を回避することが困難であるため危険です。

推奨

  • XSS を回避するために、Svelte のような安全なテンプレート機構を持つ Web フレームワークを使用してください。これは、例えば、[NNS Dapp] プロジェクトで使用されています。

  • @html in Svelte のような安全でない機能のフレームワークは使わないでください。

ログアウトが有効であることを確認する

セキュリティ上の懸念事項

ユーザーによるログアウト操作が有効でない場合、例えば、共有または公共のデバイスが使用されている場合、アカウントの乗っ取りにつながる可能性があります。

推奨

  • ログアウト時にすべてのセッションデータ(特に sessionStoragelocalStorage )、IndexedDB などをクリアしてください。

  • あるタブでログアウトが発生した場合、同じオリジンを表示している他のブラウザタブもログアウトされることを確認してください。これは、agent-js が初期化されると秘密鍵をメモリに保持するため、agent-js を使用する場合は自動的に起こりません。

プロンプトを使用してセキュリティ上重要な操作についてユーザーに警告しユーザーに明示的に確認させる

セキュリティ上の懸念事項

そうでない場合、ユーザーは誤って機密性の高いアクションを実行する可能性があります。

推奨

  • アクションの正確な結果を説明するセキュリティ警告を含むプロンプトをユーザーに表示し、明示的に確認させます。

  • 例えば、WebAuthn デバイスを使用して、ユーザーに特定の重要なアクションやトランザクションを確認させることです。これは例えば、トークンや Cycle の転送が含まれる場合に推奨されます。例えば、NNS Dapp でハードウェアウォレットを使用すると、これが実現されます。