モバイルアプリの認証アーキテクチャ

認証と認可の問題はよくあるセキュリティ脆弱性です。実際、それらは OWASP Top 10 で一貫して二位という高いランクをつけています。

ほとんどのモバイルアプリは何かしらのユーザー認証を実装しています。認証および状態管理ロジックの一部はバックエンドサービスで実行されますが、認証はほとんどのモバイルアプリアーキテクチャに不可欠な要素であるため、一般的な実装を理解することが重要です。

基本的な概念は iOS と Android で同一なので、この一般的なガイドではよくある認証と認可アーキテクチャと落とし穴について説明します。ローカル認証や生体認証などの OS 固有の認証問題についてはそれぞれ OS 固有の章で説明します。

一般的な前提

適切な認証が設定されていること

認証と認可をテストする際には以下の手順を実行します。

  • アプリが使用する追加の認証要素を特定します。

  • 重要な機能を提供するすべてのエンドポイントを突き止めます。

  • 追加の要素がすべてのサーバー側エンドポイントで厳密に実施されていることを検証します。

認証バイパス脆弱性はサーバーで認証状態が一貫して実施されておらず、クライアントが状態を改竄できる場合に存在します。バックエンドサービスはモバイルクライアントからのリクエストを処理している間、一貫して認可チェックを実施する必要があります。つまり、リソースがリクエストされるごとにユーザーがログインし認可されていることを検証します。

OWASP Web Testing Guide の以下の例を考えてみます。この例では、ウェブリソースは URL を介してアクセスされており、認証状態は GET パラメータを介して渡されます。

http://www.site.com/page.asp?authenticated=no

クライアントはリクエストとともに送られる GET パラメータを任意に変更できます。クライアントが authenticated パラメータの値を単に "yes" に変更して、事実上認証をバイパスすることを妨げるものは何もありません。

これは実際に見つかることはないであろう過度に単純化した例ですが、プログラマーは認証状態を維持するために Cookie などの「隠された」クライアント側パラメータに依存することがあります。彼らはこれらのパラメータが改竄できないと想定しています。例えば、次の Nortel Contact Center Manager の古典的な脆弱性 を考えてみます。Nortel のアプライアンスの管理ウェブアプリケーションは "isAdmin" Cookie に依存して、ログインユーザーに管理者特権を付与する必要があるかどうかを判断していました。その結果、以下のように Cookie の値を設定するだけで管理者アクセスを取得できました。

isAdmin=True

かつてセキュリティ専門家はセッションベースの認証を使用し、サーバー上でのみセッションデータを維持することを推奨していました。これによりクライアント側でセッション状態が改竄されることを防ぎます。ただし、セッションベース認証の代わりにステートレス認証を使用することの重要な点はサーバーでセッション状態を 持たない ことです。代わりに、状態はクライアント側トークンに格納され、すべてのリクエストとともに送信されます。この場合には、 isAdmin のようなクライアント側パラメータを見ることは完全に正常です。

改竄を防ぐためには暗号化署名をクライアント側トークンに追加します。もちろん、物事は悪くなる可能性があり、ステートレス認証の一般的な実装は攻撃に対して脆弱です。例えば、一部の JSON Web Token (JWT) 実装の署名検証は 署名タイプを "None" に設定すること により無効化できます。

パスワードのベストプラクティス

パスワードが認証に使用される場合、パスワードの強度は重要事項です。パスワードポリシーはエンドユーザーが遵守すべき要件を定義します。パスワードポリシーは一般的にパスワードの長さ、パスワードの複雑さ、およびパスワードのトポロジーを指定します。「強力な」パスワードポリシーにより手動または自動のパスワードクラッキングが困難あるいは不可能になります。詳細については OWASP Authentication Cheat Sheet を参照してください。

認証のテストに関する一般的なガイドライン

認証にはすべてに適応できる万能なアプローチはありません。アプリの認証アーキテクチャをレビューするときには、まず認証方法が特定のコンテキストで適切かどうかを考慮すべきです。認証は以下の一つ以上に基づいて行うことができます。

  • ユーザーが知っていること (パスワード, PIN, パターンなど)

  • ユーザーが持っているもの (SIM カード, ワンタイムパスワードジェネレータ, ハードウェアトークン)

  • ユーザーの生体属性 (指紋, 網膜, 音声)

モバイルアプリにより実装される認証手続きの数は、機能やアクセスされるリソースの機密性に依存します。認証機能をレビューする際には業界のベストプラクティスを参照します。ユーザー名/パスワード認証 (適正なパスワードポリシーと組み合わせた) はユーザーログインがありそれほど機密性が高くはないアプリには一般的に十分であると考えられています。この形式の認証はほとんどのソーシャルメディアアプリで使用されています。

機密性の高いアプリでは、通常、二要素認証を加えることが適切です。これには非常に機密性の高い情報 (クレジットカード番号など) へのアクセスを提供したりユーザーが送金できるアプリが含まれます。一部の業界では、これらのアプリは特定の標準にも準拠する必要があります。例えば、金融アプリは Payment Card Industry Data Security Standard (PCI DSS) 、グラム・リーチ・ブライリー法、サーベンス・オクスリー法 (SOX) に確実に準拠する必要があります。米国の医療部門のコンプライアンスに関する考慮事項には、医療保険の相互運用性と説明責任に関する法令 (HIPAA) および Patient Safety Rule があります。

ステートフル認証とステートレス認証

通常、モバイルアプリはトランスポート層として HTTP を使用します。HTTP プロトコル自体はステートレスであるため、ユーザーの後続の HTTP リクエストをそのユーザーに関連付ける方法が必要です。そうでない場合、ユーザーのログイン資格情報はリクエストごとに送信する必要があります。また、サーバーとクライアントの両方がユーザーデータ (ユーザーの権限や役割など) を追跡し続ける必要があります。これには二つの異なる方法で行うことが可能です。

  • ステートフル 認証では、ユーザーがログインする際に一意のセッション ID が生成されます。以降のリクエストでは、このセッション ID はサーバーに保存されているユーザー詳細への参照として機能します。セッション ID は 不透明 であり、ユーザーデータは含まれていません。

  • ステートレス 認証では、すべてのユーザー識別情報がクライアント側トークンに保存されます。トークンは任意のサーバーやマイクロサービスに渡すことができ、サーバーでセッション状態を維持する必要がなくなります。スレートレス認証は多くの場合ユーザーのログイン時にトークンを生成、署名、およびオプションで暗号化する認可サーバーに組み込まれています。

ウェブアプリケーションは一般的にクライアント側 Cookie に保存されているランダムセッション ID でステートフル認証を使用します。モバイルアプリはしばしば同様の方法でステートフルセッションを使用しますが、ステートレストークンベースのアプローチがさまざまな理由で一般的になりつつあります。

  • サーバーにセッション状態を保存する必要がなくなるため、スケーラビリティとパフォーマンスが向上します。

  • トークンにより開発者はアプリから認証を分離できます。トークンは認証サーバーで生成でき、認証スキームはシームレスに変更できます。

モバイルセキュリティテスト担当者として、両方のタイプの認証に精通しているべきです。

ステートフル認証

ステートフル (または「セッションベース」) 認証はクライアントとサーバーの両方の認証レコードにより特徴付けられます。認証フローは以下の通りです。

  1. アプリはユーザーの資格情報を含むリクエストをバックエンドサーバーに送信します。

  2. サーバーは資格情報を検証します。資格情報が有効である場合、サーバーはランダムセッション ID とともに新しいセッションを作成します。

  3. サーバーはそのセッション ID を含むレスポンスをクライアントに送信します。

  4. クライアントは後続のすべてのリクエストとともにそのセッション ID を送信します。サーバーはセッション ID を妥当性確認し、関連するセッションレコードを取得します。

  5. ユーザーがログアウトした後、サーバー側セッションレコードは破壊され、クライアントはセッション ID を破棄します。

セッションが不適切に管理されると、正規ユーザーのセッションを危殆化する可能性のあるさまざまな攻撃に対して脆弱になり、攻撃者がそのユーザーになりすますことができます。これによりデータの損失、機密性の危殆化、および不正行為が発生する可能性があります。

ベストプラクティス:

機密情報や機能を提供するサーバー側エンドポイントをすべて見つけ、認可の一貫した実施を検証します。バックエンドサービスはユーザーのセッション ID またはトークンを検証し、ユーザーがリソースにアクセスするために十分な権限を持っていることを確認する必要があります。セッション ID またはトークンが欠落しているか無効である場合には、そのリクエストは拒否する必要があります。

以下を確認します。

  • セッション ID はサーバー側でランダムに生成されています。

  • その ID は簡単には推測できません (適切な長さとエントロピーを使用しています) 。

  • セッション ID は常にセキュアな接続 (HTTPS など) の上で交換されています。

  • モバイルアプリはセッション ID を永続的なストレージに保存していません。

  • サーバーはユーザーが特権アプリケーション要素にアクセスしようとするたびにそのセッションを検証します (セッション ID は有効であり、適切な認可レベルに対応している必要があります) 。

  • タイムアウトまたはユーザーがログアウトした後、セッションはサーバー側で終了し、モバイルアプリ内のセッション情報は削除されています。

認証はゼロから実装すべきではなく、実績のあるフレームワークの上に構築すべきです。多くの著名なフレームワークは既製の認証およびセッション管理機能を提供します。アプリが認証にフレームワーク API を使用している場合、ベストプラクティスについてはそのフレームワークのセキュリティドキュメントをチェックします。一般的なフレームワークについてのセキュリティガイドは以下のリンクから利用可能です。

サーバー側認証のテストについての優れたリソースには OWASP Web Testing Guide があり、特に Testing Authentication および Testing Session Management の章をご覧ください。

ステートレス認証

トークンベース認証は HTTP リクエストごとに (サーバーにより検証済みの) 署名トークンを送信することにより実装されています。最も一般的に使用されるトークン形式は JSON Web Token であり、RFC7519 で定義されています。JWT は完全なセッション状態を JSON オブジェクトとしてエンコードできます。したがって、サーバーはセッションデータや認証情報を保存する必要はありません。

JWT トークンはドットで区切られた三つの Base64Url エンコードされたパーツで構成されています。トークン構造は以下のとおりです。

base64UrlEncode(header).base64UrlEncode(payload).base64UrlEncode(signature)

以下の例は Base64Url-encoded JSON Web Token を示しています。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
G4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

header は一般的に二つのパーツで構成されています。トークンタイプ、これは JWT です、および署名の計算に使用されるハッシュアルゴリズムです。上記の例では、header は以下のようにデコードされます。

{"alg":"HS256","typ":"JWT"}

トークンの二番目のパーツは payload で、いわゆる要求 (claim) が含まれています。要求はエンティティ (通常はユーザー) および追加のメタデータに関するステートメントです。以下に例を示します。

{"sub":"1234567890","name":"John Doe","admin":true}

signature は JWT header で指定されたアルゴリズムをエンコードされた header 、エンコードされた payload 、および secret 値に適用することにより作成されます。例えば、HMAC SHA256 アルゴリズムを使用する場合、signature は以下の方法で作成されます。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

secret は認証サーバーとバックエンドサービスとの間で共有されていることに注意します。クライアントはそれを知りません。これはトークンが正規の認証サービスから取得されたことを証明しています。またクライアントがトークンに含まれる claim を改竄することも防止します。

ベストプラクティス:

実装が JWT ベストプラクティス に準拠していることを検証します。

  • トークンを含むすべての着信リクエストについて HMAC がチェックされていることを検証します。

  • 秘密署名鍵 (private signing key) や HMAC 秘密鍵 (HMAC secret key) がクライアントと決して共有されていないことを検証します。発行者および検証者のみが利用できるようにすべきです。

  • 個人識別情報などの機密データが JWT に埋め込まれていないことを検証します。たとえば、base64 エンコードされた JWT をデコードして、どのようなデータを送信していてそのデータが暗号化されているかどうかを調べます。何らかの理由で、このような情報をトークンで送信する必要があるアーキテクチャの場合、ペイロード暗号化が適用されていることを確認します。OWASP JWT Cheat Sheet のサンプル Java 実装を参照してください。

  • リプレイ攻撃は JWT に一意の識別子を与える jti (JWT ID) クレームで対処されていることを確認します。

  • クロスサービスリレー攻撃はトークンに資格を与えるアプリケーションを定義する aud (audience) クレームで対処されていることを確認します。

  • KeyChain (iOS) や KeyStore (Android) などを使用して、トークンがモバイルフォンにセキュアに保存されていることを検証します。

  • ハッシュアルゴリズムが強制されていることを検証します。一般的な攻撃としては、トークンを改変して空の署名 (例, signature = "") を使用し、署名アルゴリズムを none に設定して、「トークンの完全性がすでに検証されている」ことを示すものがあります。 一部のライブラリ では none アルゴリズムで署名されたトークンを検証済み署名付きの有効なトークンであるものとして扱う可能性があるため、アプリケーションは改変されたトークンのクレームを信頼してしまいます。

  • トークンに "exp" 有効期限クレーム が含まれていて、バックエンドでは期限切れのトークンを処理しないことを検証します。トークンを付与する一般的な方法は アクセストークンとリフレッシュトークン を組み合わせたものです。ユーザーがログインする際、バックエンドサービスは短命のアクセストークン (access token) と長命のリフレッシュトークン (refresh token) を発行します。アプリケーションはアクセストークンの有効期限が切れた場合に、リフレッシュトークンを使用して新しいアクセストークンを取得できます。

上記の脆弱性をテストする際に役立つ二つの異なる Burp プラグインがあります。

また、追加情報として OWASP JWT Cheat Sheet も確認してください。

OAuth 2.0

OAuth 2.0 はサードパーティアプリケーションが API やウェブ対応アプリケーションなどのリモート HTTP サービス上のユーザーアカウントへの制限付きアクセスを取得できるようにする認可フレームワークです。

OAuth2 の一般的な用法は以下の通りです。

  • ユーザーからアカウントを使用してオンラインサービスにアクセスする許可を取得すること。

  • ユーザーの代わりにオンラインサービスを認証すること。

  • 認証エラーを処理すること。

OAuth 2.0 によると、ユーザーのリソースにアクセスを求めるモバイルクライアントは最初に 認証サーバー に対する認証をユーザーに要求する必要があります。ユーザーの承認を受けて、認可サーバーはトークンを発行してアプリがユーザーの代わりに動作できるようにします。OAuth2 仕様では特定の種類の認証やアクセストークンの形式を定義していないことに注意します。

プロトコル概要

OAuth 2.0 は四つのロールを定義しています。

  • リソース所有者: アカウント所有者

  • クライアント: アクセストークンを使用してユーザーのアカウントにアクセスしようとするアプリケーション

  • リソースサーバー: ユーザーアカウントをホストします

  • 認可サーバー: ユーザー識別子を検証してアプリケーションにアクセストークンを発行します

注意: API はリソースサーバーと認可サーバーの両方のロールを果たします。したがって、両方を API と呼んでいます。

図のステップのより 詳細な説明 は以下のとおりです。

  1. アプリケーションはサービスリソースにアクセスするためにユーザー認可を要求します。

  2. ユーザーがリクエストを認可すると、アプリケーションは認可グラントを受け取ります。認可グラントにはいくつかの形式 (explicit, implicit, など) があります。

  3. アプリケーションは認可グラントとともに独自の識別子の認証を提示することにより認可サーバー (API) からアクセストークンを要求します。

  4. アプリケーション識別子が認証され認可グラントが有効である場合、認可サーバー (API) はアプリケーションにアクセストークンを発行し、認可プロセスを完了します。アクセストークンにはコンパニオンリフレッシュトークンが含まれることがあります。

  5. アプリケーションはリソースサーバー (API) からリソースを要求し、認証用のアクセストークンを提示します。アクセストークンはいくつかの方法で (例えば、ベアラトークンとして) 使用される可能性があります。

  6. アクセストークンが有効である場合、リソースサーバー (API) はアプリケーションにリソースを提供します。

OAuth2 では、ユーザーエージェント (user agent) は認証を実行するエンティティです。OAuth2 認証は外部ユーザーエージェント (Chrome や Safari など) を介して実行することも、アプリ自体の中 (アプリに埋め込まれた WebView や認証ライブラリなど) で実行することも可能です。二つのモードは本質的にいずれかが「より優れて」いるわけではありません。どちらを選択するかはアプリのユースケースと脅威モデルによって異なります。

外部ユーザーエージェント: 外部ユーザーエージェント (external user agent) を使用することはソーシャルメディアアカウント (Facebook, Twitter など) とやり取りする必要があるアプリに適した方法です。この方法の利点は以下の通りです。

  • ユーザーの資格情報はアプリに直接開示されることはありません。これによりアプリがログインプロセス時に資格情報を取得 (「資格情報フィッシング」) できないことを保証します。

  • アプリ自体に認証ロジックを追加する必要はほとんどないため、コーディングエラーを防止します。

欠点としては、ブラウザの動作を制御する方法がないことがあげられます (例えば、証明書ピンニングをアクティブにするなど) 。

埋め込みユーザーエージェント: 埋め込みユーザーエージェント (embedded user agent) を使用することは企業アカウントと連携するなど、閉じたエコシステム内で動作する必要があるアプリに適した方法です。たとえば、OAuth2 を使用して銀行の認証サーバーからアクセストークンを取得し、それを使用して多くのマイクロサービスにアクセスする銀行アプリを考えてみましょう。そのような場合、資格情報フィッシングは実行可能なシナリオではありません。認証プロセスは外部コンポーネントに信頼を置くのではなく、(できれば) 慎重に保護された銀行アプリないに保持することが望ましいと考えられます。

ベストプラクティス

その他のベストプラクティスと詳細情報については以下のソースドキュメントを参照してください。

ベストプラクティスには以下のようなものがありますが、これらに限定されません。

  • ユーザーエージェント:

    • ユーザーが信頼性を視覚的に検証する方法 (例、Transport Layer Security (TLS) の確認、ウェブサイトメカニズムなど) を備えるべきです。

    • 中間者攻撃を防ぐには、クライアントは接続の確立時にサーバーが提示した公開鍵で完全修飾ドメイン名を検証すべきです。

  • グラントの種別:

    • ネイティブアプリでは、暗黙的グラントではなくコードグラントを使用すべきです。

    • コードグラントを使用する場合、コードグラントを保護するために PKCE (Proof Key for Code Exchange) を実装すべきです。サーバーでもそれを実装していることを確認します。

    • 認証 "code" は短命とすべきであり、受信後即時に使用されるべきです。認証コードは一時メモリにのみ存在し、保存やログ記録されていないことを検証します。

  • クライアントシークレット:

    • 共有シークレットをクライアントの同一性を証明するために使用すべきではありません。クライアントは偽装される可能性があるためです ("client_id" はすでに証拠として機能しています) 。クライアントシークレットを使用する場合には、それらがセキュアなローカルストレージに保存されていることを確認します。

  • エンドユーザー資格情報:

    • TLS など、トランスポート層の手法を使用してエンドユーザー資格情報の送信を保護します。

  • トークン:

    • アクセストークンを一時メモリに保持します。

    • アクセストークンは暗号化された接続の上で送信する必要があります。

    • エンドツーエンドの機密性が保証できない場合、またはトークンが機密情報やトランザクションへのアクセスを提供する場合、アクセストークンのスコープと期間を狭めます。

    • アプリがアクセストークンをベアラトークンとして使用し、他にクライアントを特定する方法がない場合、トークンを盗み出した攻撃者はそれらに関連付けられたスコープとすべてのリソースにアクセスできることに注意します。

    • リフレッシュトークンをセキュアなローカルストレージに保存します。これらは長期的な資格情報です。

User Logout

サーバー側セッションの破棄に失敗することは、最も一般的なログアウト機能実装エラーのひとつです。このエラーはユーザーがアプリケーションからログアウトした後でもセッションまたはトークンを存続させます。有効な認証情報を取得した攻撃者は引き続きそれを使用してユーザーのアカウントをハイジャックできます。

多くのモバイルアプリはユーザーを自動的にログアウトしません。顧客には不便であるため、ステートレス認証を実装する際に下された判断などさまざまな理由があります。アプリケーションは依然としてログアウト機能を持つべきであり、ベストプラクティスに従って実装し、ローカルに保存されているすべてのトークンおよびセッション識別子を破棄すべきです。

セッション情報がサーバー上に保存されている場合、そのサーバーにログアウトリクエストを送信することによりそのセッション情報を破棄すべきです。高リスクのアプリケーションの場合、トークンを無効にすべきです。トークンやセッション識別子を削除しなければ、そのトークンが漏洩した場合にアプリケーションへの不正アクセスを生じる可能性があります。 他の機密情報も削除すべきであることに注意します。適切に消去されていない情報は後で、例えばデバイスバックアップの中で、漏洩する可能性があるためです。

適切なサーバー側ログアウトに対するセッション終了のさまざまな例を以下に示します。

ステートレス認証でアクセストークンおよびリフレッシュトークンを使用する場合、それらをモバイルデバイスから削除すべきです。サーバー上でリフレッシュトークンを無効にすべきです

OWASP Web Testing Guide (WSTG-SESS-06) には詳細な説明とより多くのテストケースが含まれています。

補助認証

認証スキームは パッシブコンテキスト認証 により補完されることがよくあります。 これは以下を取り込むことができます。

  • 位置情報

  • IP アドレス

  • 時刻

  • 使用されているデバイス

理想的には、このようなシステムではユーザーのコンテキストを以前に記録されたデータと比較し、アカウントの悪用や不正の可能性を示す異常を識別します。このプロセスはユーザーには分かりきったことですが、攻撃者にとって強力な抑止力となり得ます。

二要素認証

二要素認証 (2FA) はユーザーが機密性の高い機能やデータにアクセスできるようにするアプリの標準です。一般的な実装では一番目の要素にパスワードを使用し、二番目の要素に以下のいずれかを使用します。

  • SMS によるワンタイムパスワード (SMS-OTP)

  • 電話呼び出しによるワンタイムパスワード

  • ハードウェアまたはソフトウェアトークン

  • PKI およびローカル認証と組み合わせたプッシュ通知

使用するオプションが何であれ、常にサーバー側で適用および検証する必要があり、クライアント側で行ってはいけません。そうしないと 2FA はそのアプリ内で容易にバイパスできます。

2FA ユーザーのセッションのログイン時またはそれ以降で実行できます。

例えば、ユーザー名と PIN で銀行アプリにログインした後、そのユーザーは機密性の低いタスクを実行することを認可されます。ユーザーが銀行振り込みを実行しようとした場合、二番目の要素 (「ステップアップ認証」) が提示される必要があります。

ベストプラクティス:

  • 2FA を自作しない: 二要素認証メカニズムにはサードパーティライブラリ、外部アプリの使用、開発者が独自に実装したチェックなどさまざまなものがあります。

  • 短命の OTP を使用する: OTP は一定時間 (通常は 30 秒) のみ有効とし、OTP を数回 (通常は 3 回) 間違って入力した後は提供された OTP が無効になり、ユーザーはランディングページにリダイレクトされるかログアウトすべきです。

  • トークンの安全に保管する: この種の攻撃を防止するには、アプリケーションは何らかのユーザートークンや以前安全に (Keychain/KeyStore 内などに) 保存されたユーザーに関連するその他の動的情報を常に検証すべきです。

SMS-OTP

SMS により送信されるワンタイムパスワード (OTP) は二要素認証の一般的な二番目の要素ですが、この方法には欠点があります。2016年に、NIST は「SMS メッセージには傍受またはリダイレクトされるリスクがあるため、新しいシステムの実装者は代替認証子を慎重に検討すべき (SHOULD) である。」と提案しました。以下に SMS-OTP への攻撃を成功させないための関連する脅威と提案のリストを示します。

脅威:

  • ワイヤレス傍受: 攻撃者は通信ネットワーク内のフェムトセルやその他の既知の脆弱性を悪用することにより SMS メッセージを傍受できます。

  • トロイの木馬: テキストメッセージにアクセスできる悪意のあるアプリケーションをインストールすると、OTP を別の番号またはバックエンドに転送される可能性があります。

  • SIM SWAP 攻撃: この攻撃では、攻撃者はその電話会社に電話するか、電話会社に働きかけ、被害者の番号を攻撃者が所有する SIM カードに移動させます。成功すると、攻撃者は被害者の電話番号に送信された SMS メッセージを見ることができます。これには二要素認証で使用されるメッセージが含まれます。

  • 検証コード転送攻撃: このソーシャルエンジニアリング攻撃は OTP を提供する会社に対するユーザーの信頼に依存しています。この攻撃では、ユーザーはコードを受け取り、以降は情報を受信したのと同じ手段を使用してコードを中継するよう求められます。

  • ボイスメール: 一部の二要素認証スキームでは SMS が選ばれないまたは利用できない場合に OTP を電話呼び出しにより送信できます。これらの呼び出しの多くは、応答されない場合、ボイスメールに情報を送信します。攻撃者がボイスメールにアクセスできた場合、OTP を使用してユーザーのアカウントにアクセスすることも可能です。

OTP に SMS を使用する場合に悪用の可能性を減らすためのいくつかの提案を以下に示します:

  • メッセージング: OTP を SMS により送信する場合、ユーザーに次のことを知らせるメッセージを含めるようにします。 1) コードを要求していない場合の対処方法 2) 会社はパスワードまたはコードを中継するような要求を電話したりテキストを送ったりすることはないこと

  • 専用チャンネル: OS プッシュ通信機能 (iOS の APN および Android の FCM) を使用する場合、OTP を登録済みアプリケーションにセキュアに送信できます。この情報は、SMS と比較して、他のアプリケーションからアクセス可能ではありません。OTP の代わりにプッシュ通信はポップアップをトリガーして要求されたアクセスを承認できます。

  • エントロピー: 高いエントロピーを持つ認証子を使用して OTP をクラックまたは推測しにくくし、少なくとも 6 桁を使用します。ユーザーがアプリにコピーするために覚えておく必要がある場合には数字が小さなグループに分かれていることを確認します。

  • ボイスメールの回避: ユーザーが電話呼び出しを受けることを選択した場合、OTP 情報をボイスメールとして残さないようにします。

SMS-OTP の研究:

  • [#dmitrienko] Dmitrienko, Alexandra, et al. "On the (in) security of mobile two-factor authentication." International Conference on Financial Cryptography and Data Security. Springer, Berlin, Heidelberg, 2014.

  • [#grassi] Grassi, Paul A., et al. Digital identity guidelines: Authentication and lifecycle management (DRAFT). No. Special Publication (NIST SP)-800-63B. 2016.

  • [#grassi2] Grassi, Paul A., et al. Digital identity guidelines: Authentication and lifecycle management. No. Special Publication (NIST SP)-800-63B. 2017.

  • [#konoth] Konoth, Radhesh Krishnan, Victor van der Veen, and Herbert Bos. "How anywhere computing just killed your phone-based two-factor authentication." International Conference on Financial Cryptography and Data Security. Springer, Berlin, Heidelberg, 2016.

  • [#mulliner] Mulliner, Collin, et al. "SMS-based one-time passwords: attacks and defense." International Conference on Detection of Intrusions and Malware, and Vulnerability Assessment. Springer, Berlin, Heidelberg, 2013.

  • [#siadati] Siadati, Hossein, et al. "Mind your SMSes: Mitigating social engineering in second factor authentication." Computers & Security 65 (2017): 14-28.

  • [#siadati2] Siadati, Hossein, Toan Nguyen, and Nasir Memon. "Verification code forwarding attack (short paper)." International Conference on Passwords. Springer, Cham, 2015.

プッシュ通信と PKI を使用したトランザクション署名

二番目の要素を実装するもう一つの代替であり強力なメカニズムはトランザクション署名です。

トランザクション署名は重要なトランザクションに対するユーザーの承認の認証が必要です。非対称暗号化はトランザクション署名を実装する最良の方法です。ユーザーがサインアップすると、アプリは公開鍵と秘密鍵のペアを生成し、バックエンドに公開鍵を登録します。秘密鍵は KeyStore (Android) または KeyChain (iOS) にセキュアに保存されます。トランザクションを認可するために、バックエンドはモバイルアプリにトランザクションデータを含むプッシュ通知を送信します。それからユーザーはそのトランザクションを確認または拒否するように求められます。確認後、ユーザーは (PIN または指紋を入力して) キーチェーンをアンロックするよう促され、データはユーザーの秘密鍵で署名されます。その後、署名されたトランザクションはサーバーに送信され、ユーザーの公開鍵で署名が検証されます。

ログインアクティビティとデバイスブロッキング

アプリはアプリ内のすべてのログインアクティビティについてユーザーに通知し、特定のデバイスをブロックできるようにすることがベストプラクティスです。これはさまざまなシナリオに分類できます。

  1. アプリケーションはアカウントが別のデバイスで使用されたときにプッシュ通信を提供し、さまざまなアクティビティをユーザーに通知します。ユーザーはプッシュ通知を介してアプリを開いた後にこのデバイスをブロックできます。

  2. アプリケーションはログイン後の最後のセッションの概要を提供します。前のセッションが現在の構成と比較して異なる構成 (例、位置情報、デバイス、アプリバージョン) の場合、ユーザーに疑わしいアクティビティを報告し、前のセッションで使用されたデバイスをブロックするオプションを持つべきです。

  3. アプリケーションはログイン後の最後のセッションの概要を常に提供します。

  4. アプリケーションはユーザーが監査ログを参照できるセルフサービスポータルを持ちます。これによりユーザーはログインしているさまざまなデバイスを管理できます。

開発者は特定のメタ情報を使用してアプリケーション内のさまざまなアクティビティやイベントを関連付けることができます。これによりユーザーは疑わしい動作を見つけやすくなり、該当するデバイスをブロックしやすくなります。メタ情報には以下のものがあります。

  • デバイス: ユーザーはアプリが使用されているすべてのデバイスを明確に識別できます。

  • 日付と時刻: ユーザーはアプリが使用された最新の日付と時刻を明確に参照できます。

  • 位置情報: ユーザーはアプリが使用された最新の位置情報を明確に識別できます。

アプリケーションはアプリケーション内のそれぞれの機密性の高いアクティビティの後に更新されるアクティビティ履歴のリストを提供できます。監査するアクティビティの選択は処理するデータとチームが許容するセキュリティリスクのレベルに基づいてアプリケーションごとに行う必要があります。下記は通常監査される一般的な機密性の高いアクティビティのリストです。

  • ログイン試行

  • パスワード変更

  • 個人識別情報変更 (名前、電子メールアドレス、電話番号、など)

  • 機密性の高いアクティビティ (購入、重要なリソースへのアクセス、など)

  • 利用規約条項への同意

有料コンテンツには特に注意が必要であり、追加のメタ情報 (例、費用、クレジット、など) を使用して操作全体のパラメータに関するユーザーの知識を確保します。

さらに、特定のトランザクションが実際に (完全性) および誰により (真正性) 実行されたかを証明するために、否認防止メカニズムを機密性の高いトランザクション (例、有料コンテンツアクセス、利用規約条項への同意、など) に適用すべきです。

最後に、特定のオープンセッションをユーザーがログアウトできるようにすべきです。場合によっては、デバイス識別子を使用して特定のデバイスを完全にブロックするのもよいかもしれません。

Last updated