C7: 安全なデジタルアイデンティティ (Secure Digital Identities)
説明
デジタルアイデンティティはオンライン取引に関わる個人、組織 (または別の主体) の固有の表現です。認証は個人やエンティティが本人であることを検証するプロセスです。
セッション管理とは、ユーザーが再認証することなくシステムを使い続けられるように、サーバーがユーザーの認証状態を維持するプロセスです。 デジタルアイデンティティ、認証、セッション管理は非常に複雑なトピックです。ここではデジタルアイデンティティのトピックの表面だけを取り上げています。最も有能なエンジニアリング人材がほとんどのアイデンティティソリューションに関わる複雑さを維持する責任を負うようにします。
NIST Special Publication 800-63B: Digital Identity Guidelines (Authentication and Life Cycle Management) は、デジタルアイデンティティ、認証、セッション管理の実装に関する確かなガイダンスを提供しています。以下は、強力なデジタルアイデンティティコントロールをアプリケーションに実装されるようにするための、安全な実装に関する推奨事項です。
認証保証レベル
NIST 800-63b は認証保証レベル (Authentication Assurance Level, AAL) と呼ばれる三つの認証保証レベルについて説明している。
レベル 1 : パスワード: 最初のレベルである AAL レベル 1 は PII やその他のプライベートデータを含まない低リスクのアプリケーションに予約されている。AAL レベル 1 では、通常、パスワード (あなたが知っているもの) を使用する単一要素認証のみが要求されます。パスワード (または一般的なクレデンシャル) のセキュリティは最も重要であり、これは安全なストレージ (鍵導出機能などを使用) と、安全なパスワードリセットフローなどの、対応するプロセスの両方を含みます。
レベル 2 : 多要素認証: NIST 800-63b AAL レベル 2 は「自己申告された PII またはオンラインで利用可能なその他の個人情報」を含む、より高リスクのアプリケーションに予約されています。AAL レベル 2 では、OTP やその他の形式の多要素実装を含む多要素認証が要求されます。
レベル 3 : 暗号ベースの認証: NIST 800-63b 認証保証レベル 3 (AAL3) は、危殆化したシステムの影響が個人の損害、重大な金銭的損失、公共の利益の損害、民事または刑事上の違反につながる可能性がある場合に要求されます。AAL3 は「暗号プロトコルによる鍵の所有証明に基づく」認証を要求します。このタイプの認証は最も強力なレベルの認証保証を実現するために使用されます。これは通常、ハードウェア暗号モジュールを通じて行われます。ウェブアプリケーションを開発する場合、これは一般的に WebAuthn や PassKeys につながります。
レベル 2 : 多要素認証
NIST 800-63b AAL レベル 2 は「自己申請された PII またはオンラインで利用可能なその他の個人情報」を含む、より高リスクのアプリケーションに予約されています。AAL レベル 2 では、OTP やその他の形式の多要素実装を含む多要素認証が要求されます。
多要素認証 (MFA) は以下を組み合わせて本人確認を要求することで、ユーザーが本人であることを確保します。
あなたが知っているもの (Something you know) – パスワードや PIN
あなたが持っているもの (Something you own) – トークンやスマホ。スマホを使用する場合には FIDO2 などの標準化されたプロトコルに従った標準認証アプリケーションを使用してください。
あなた自身であるもの (Something you are) – 指紋などの生体認証
パスワードを唯一の要素として使用すると、セキュリティが弱くなります。多要素認証ソリューションは、攻撃者がサービスを認証するために複数の要素を取得することを要求するため、より堅牢なソリューションを提供します。
生体認証は、認証の単一要素として採用される場合、デジタル認証に許容されるシークレットとはみなされないことに留意してください。生体認証は、本人の許諾の有無にかかわらずオンラインやカメラ付きスマホで人物の写真を撮影したり (顔画像など)、本人が触れたものから採取したり (潜伏している指紋など)、高解像度画像からキャプチャしたり (虹彩パターンなど) できます。生体認証は、物理的な認証子 (あなたが持っているもの) を使用する多要素認証の一部としてのみ使用しなければなりません。たとえば、多要素ワンタイムパスワード (OTP) デバイスにアクセスすると、ワンタイムパスワードを生成し、ユーザーが検証器に対して手動で入力します。
レベル 3 : 暗号ベースの認証
NIST 800-63b 認証保証レベル 3 (AAL3) は、危殆化したシステムの影響が個人の損害、重大な金銭的損失、公共の利益の損害、民事または刑事上の違反につながる可能性がある場合に要求されます。AAL3 は「暗号プロトコルによる鍵の所有証明に基づく」認証を要求します。このタイプの認証は最も強力なレベルの認証保証を実現するために使用されます。これは通常、ハードウェア暗号モジュールを通じて行われます。ウェブアプリケーションを開発する場合、これは一般的に WebAuthn や PassKeys につながります。
セッション管理: クライアントサイドセッションとサーバーサイドセッション
HTTP はそれ自体がセッションレスプロトコルです。つまり、リクエスト間でデータが共有されません。私たちがどのようにウェブを使用しているかを見てみると、たとえばウェブサイトにログインすると、後続のリクエストの間もログインを維持するため、ユーザーに見えるものではないことが明らかです。これはセッション管理が HTTP 上に実装されているから可能なのです。
最初のユーザー認証が成功すると、アプリケーションはこの認証状態を追跡して、一定時間維持することを選択できます。これにより、ユーザーはリクエストごとに再認証する必要なくアプリケーションを使い続けることができます。このユーザー状態の追跡をセッション管理と呼びます。
セッション管理はクライアントサイドとサーバーサイドのセッション管理に大別できます。前者では、すべてのセッションデータをクライアント内に保存し、リクエストごとにサーバーに送信します。後者では、セッション固有のデータをサーバー、たとえばデータベースなど、に保存し、識別子のみをクライアントに送信します。それから、クライアントはリクエストごとにセッション識別子のみを送信し、サーバーはサーバーサイドストレージからセッションデータを取り出します。
セキュリティの観点からみると、サーバーサイドセッションには複数の利点がある。
データはクライアントに直接保存されません。これは、機密データを扱う場合などに問題となる可能性があります。さらに、クライアントサイドセッション管理ソリューションではクライアントサイドデータが改竄されていないことを確保しなければなりません。
クライアントとサーバー間で送信されるデータが少なくなります (ネットワーク帯域幅が増加したため、それほど重要ではありません)
サーバーサイドセッション管理はセッションの無効化を可能にします。たとえば、ユーザーはすべてのセッションからログアウトできます。 デフォルトでは、常にサーバーサイドセッション管理を使用しましょう。
脅威
攻撃者はセッショントークンを盗んだり予測してユーザーセッションをハイジャックし、認証されたユーザーアカウントへの認可されていないアクセスを得る可能性があります。
攻撃者は脆弱なセッション管理を悪用してセッション固定化攻撃を実行し、ユーザーに既知のセッション識別子を使用させる可能性があります。
攻撃者は認証されたセッションに対してクロスサイトリクエストフォージェリ (CSRF) 攻撃を実行して、ユーザーを騙してウェブアプリケーション上で意図しないアクションを知らないうちに実行される可能性があります。
実装
パスワードの使用について
パスワードの要件
パスワードは少なくとも以下の要件に準拠すべきです。
多要素認証 (MFA) やその他のコントロールも使用する場合、少なくとも 8 文字の長さにします。MFA が不可能な場合、少なくとも 10 文字に増やすべきです
記録するシークレットには、表示可能な ASCII 文字とスペース文字を許容すべきです
長いパスワードやパスフレーズの使用を推奨します
複雑さの要件は効果が限定的であることが判明しているため削除します。その代わりに、MFA やより長いパスワード長の採用をお勧めします
使用するパスワードが、過去の侵害ですでに漏洩したことがある一般的に使用されるパスワードではないことを確認します。上記の長さ要件を満たし、侵害されたパスワードリストにある最も一般的な上位 1000 または 10000 のパスワードをブロックすることを選択できます。次のリンクには最も一般的に見られるパスワードがあります: https://github.com/danielmiessler/SecLists/tree/master/Passwords
パスワードのローテーションを強制して、同じパスワードが非常に長期間使用されることによる潜在的な侵害を避けます
安全なパスワード回復メカニズムの実装
アプリケーションはユーザーがパスワードを忘れた場合に自分のアカウントにアクセスできるようなメカニズムを備えていることが一般的です。パスワード回復機能の優れた設計ワークフローでは多要素認証要素を使用します。たとえば、セキュリティの質問 (ユーザーが知っているもの) を尋ね、生成されたトークンをデバイス (ユーザーが持っているもの) に送信します。
詳細については Forgot_Password_Cheat_Sheet および Choosing_and_Using_Security_Questions_Cheat_Sheet をご覧ください。
安全なパスワード保管の実装
強力な認証コントロールを提供するには、アプリケーションはユーザークレデンシャルを安全に保存しなければなりません。さらに、クレデンシャル (パスワードなど) が侵害された場合でも、攻撃者がすぐにこの情報にアクセスできないように、暗号コントロールを行うべきです。詳細については OWASP Password Storage Cheat Sheet をご覧ください。
サーバーサイドセッション管理
通常、サーバーサイドセッション管理はセッション識別子の保存に使用される HTTP クッキーで実装します。新しいセッションがリクエストされると、サーバーは新しいセッション識別子を生成し、クライアント (ブラウザ) に送信します。その後のリクエストごとに、セッション識別子はクライアントからサーバーに送信され、サーバーはこのセッション識別子を使用して、サーバーサイドデータベース内のセッションデータを検索します。
セッションの生成と有効期限
ユーザーの状態はセッションで追跡されます。このセッションは一般的に従来のウェブベースのセッション管理のためにサーバー上に保存されます。そして、セッション識別子がユーザーに与えられ、ユーザーはどのサーバーサイドセッションに正しいユーザーデータを含むかを識別できます。クライアントはこのセッション識別子を維持するだけでよく、機密性の高いサーバーサイドセッションデータをクライアントから切り離すことができます。
セッション管理ソリューションを構築または実装する際に考慮すべきコントロールをいくつか以下に示します。
セッション ID が長く、一意で、ランダムである、つまり、エントロピーが高いことを確保します。
アプリケーションは認証および再認証時に新しいセッションを生成すべきです。
アプリケーションは、一定期間の非アクティブの後のアイドルタイムアウトと、セッションごとの絶対的な最大存続期間を実装すべきであり、その後ユーザーは再認証しなければなりません。タイムアウトの長さは、保護されるデータの価値に反比例すべきです。
詳細については Session Management Cheat Sheet をご覧ください。ASVS セクション 3 では追加のセッション管理要件をカバーしています。
クライアントサイドセッション管理
サーバーサイドセッションは認証の形式によっては制限になることがあります。「ステートレスサービス」は、パフォーマンス上の目的でクライアントサイドでセッションデータを管理できるため、サーバーがユーザーセッションを保存する負担を軽減します。
これらの「ステートレス」アプリケーションは一般的に現在のユーザーのアクセスパーミッションを含む短期限のアクセストークンを生成し、その後のすべてのリクエストに含まれます。クライアントがトークン内に格納されているパーミッションを変更できないように、暗号技術を使用しなければなりません。クライアントがサーバー操作をリクエストすると、クライアントは取得したアクセストークンを含め、サーバーはトークンが改竄されていないことを検証し、トークンからパーミッションを抽出します。これらのパーミッションはその後のパーミッションチェックに使用されます。
JWT (JSON Web Tokens)
JSON Web Token (JWT) はオープンスタンダード (RFC 7519) であり、当事者間で JSON オブジェクトとして情報を安全に転送するためのコンパクトで自己完結的な方法を定義します。この情報は信頼できる機関によってデジタル署名されている限り、検証できて信頼できます。JWT トークンは認証時に作成され、処理の前にサーバー (または複数のサーバー) によって検証されます。しかし、JWT は最初の作成後にサーバーに保存されないことがよくあります。JWT は一般的に作成されてから、サーバーによって保存されることなくクライアントに渡されます。トークンの完全性はデジタル署名の使用によって維持されるため、サーバーは JWT がまだ有効であり、作成後に改竄されていないことを後で検証できます。
このアプローチは、クライアントとサーバーのテクノロジが異なっていても相互作用できるという点で、ステートレスかつポータブルです。
JWT を使用している場合は、返された JWT が実際に使用している署名アルゴリズムの一つを使用していることを確認する必要があります。そうしなければ、攻撃者が NULL アルゴリズムで署名された JWT を作成しようとしたり、MAC 対署名の混同攻撃を使用したり、署名用のカスタム JWS 鍵を提供しようとする可能性があります。JWT を発行する際には、JWT の署名に安全な秘密鍵を使用していることを再確認してください。出力されたそれぞれの JWT は、オフラインクラッキング攻撃を実行するために必要なすべての情報を攻撃者に提供するため、鍵も頻繁にローテーションすべきです。
ブラウザクッキー
ブラウザクッキーは標準的なセッション管理技法を実装するウェブアプリケーションのセッション識別子を保存するための一般的な方法です。ブラウザクッキーを使用する際に考慮すべき防御策をいくつか示します。
ブラウザクッキーを認証されたユーザーのセッションを追跡するメカニズムとして使用する場合、これらは最小限のドメインとパスのセットからアクセス可能であり、セッションの有効期限またはその直後に失効するようにタグ付けすべきです。
クッキーの設定時にドメインを明示的に指定しないと、現在のオリジンがドメインとして使用されることに注意してください。これは道理にかなったデフォルトです。
クッキーの設定時にパスを指定すると、リクエストが指定されたパス内にある場合にのみ、ブラウザがクッキーを送信するように制限されることを注意してください。これは、あるアプリケーションのクッキーが同じサーバー上の別のパス内にある別のアプリケーションからアクセスされることを防ぎます。この保護は脆弱です。「他の」アプリケーションに XSS 脆弱性があり、攻撃者が iframe を導入できる場合、「パス」保護を回避できます。
'secure' フラグを設定して、転送が安全なチャネル (TLS) のみで行われるようにします。
HttpOnly フラグを設定して、JavaScript 経由でクッキーにアクセスできないようにします。
クッキーに "SameSite" 属性を追加すると、現在のブラウザの一部 がクロスサイトリクエストでクッキーを送信するのを防ぎ、クロスサイトリクエストフォージェリや情報漏洩攻撃からの保護を提供します。
防止される脆弱性
参考情報
ツール
Daniel Miessler: Most commonly found passwords
Last updated