Identifier)と呼ばれる、端末に直接は結び付かない識別子を用いてかんたんログインを実現するケースも増えてきているようです。6.0からは、ベンダ向けデバイス識別子(identifierForVendor)と広告事業者向けデバイス識別子(advertisingIdentifier)というものも登場しました。前述したUDIDのセキュリティ上の問題を理解した開発者が、UDIDの代替としてこれらの識別子を用い、かんたんログインを実装するケースも増えてきているようですが、残念ながらこれで問題が解決するというわけではありません。ここでは続けて、これらの識別子が抱えるセキュリティ上の問題について見ていくことにします。UUIDUUIDは、グローバルに一意であることが保証された識別子の総称で、iOSでは以下のコードで取得することができます。uuidRef);これらのコードで得られるUUIDは、上記のコードを実行するたびに別の値になりますが、アプリの初回起動時にUUIDを生成&永続化し、それ以降は保存された値をUDIDの代わりに使うことができます。UUIDをかんたんログインのために利用すると、UDIDと異なり、アプリごとに異なる識別子が生成されるiCloud経由でUUIDを他の端末と共有することで、デバイスをまたがったユーザー識別にも利用できるなどの利点もあります。一方で、一度アプリが削除されてしまうと同じ値を生成することはできないため、PCやiCloudなどにバックアップを取っていない限り、アプリを削除されてしまうとアカウントを復帰できなくなるといった問題も発生します。6.0では、以下のコードで、特定ベンダが提供する複数アプリ間で共通な識別子を取得することができます。UUIDString];この識別子は特定ベンダの提供するアプリ間で共有され、それらのすべてのアプリが端末から削除されるまで不変です。自社が提供するすべてのアプリにまたがったアクセス解析サービスなどでの利用が想定されます。同じベンダが提供する複数のアプリにまたがってユーザー情報を共有したい場合などに、UUIDの代わりに使われるというようなケースが多いのでしょうか。UUIDと異なりidentifierForVendorは端末にひも付いた識別子であるため、これをかんたんログインに用いる場合は、デバイスをまたいだユーザー識別は行えません(UUID同様、identifierForVendorをiCloud経由でシェアすることは可能ですが、その場合、iOSが保証する「同一ベンダに限って同一の値を返す」という性質が失われるケースがあります)。6.0以降で利用できる識別子で、以下のコードで取得できます。UUIDString];こちらはidentifierForVendorと異なり、特定デバイス上のすべてのアプリで共通の値となり、ユーザーがデバイス自体を初期化するまでは不変なため、UDIDとよく似た性質を持ちます。UDIDとの違いは、iOS自体にオプトアウトの仕組みが組み込まれており、アプリ側でアプトアウトされているかどうかチェックできることくらいでしょう。この識別子はあくまで、広告事業者がユーザーの同意の下でトラッキングを行うために提供されているものです。従って、これをかんたんログインに用いることはできません。セキュアな「かんたんログイン」のための認証トークンに必要な要素とは?ここまで、UDIDを使ったかんたんログインのセキュリティ上の問題を紹介してきました。6.0以降に登場したidentifierForVendor、advertisingIdentifierを紹介しました。ここからは、これらの識別子を「認証トークン」として用いた時に、それぞれの識別子の特徴によりどんなセキュリティ上の問題が生まれるのかを、少し一般化して見ていきましょう。Tokenとの比較も行います。これまでの連載第1回〜第4回の記事も参考にしながら読み進めてください。【関連記事】http://www.atmarkit.co.jp/fsecurity/rensai/digid01/01.htmlhttp://www.atmarkit.co.jp/ait/articles/1209/10/news105.htmlhttp://www.atmarkit.co.jp/ait/articles/1209/20/news140.htmlhttp://www.atmarkit.co.jp/ait/articles/1209/27/news138.html認証トークンに必要な条件ある文字列を認証トークンとして利用するためには、さまざまな条件を満たす必要があります。どのような条件を満たす必要があるかは、以下の資料などを参考にするとよいでしょう。Programmehttp://www.itu.int/itu-t/workprog/wp_item.aspx?isn=6842本稿ではそれらすべてについては述べませんが、以下のような主な条件について考えてみます。そのトークンは、行使者しか知らないor作成できないものであることそのトークンは、リプレイ攻撃ができないことそのトークンは、書き換え攻撃ができないことまた上述の資料とは別に、以下の条件についても考えます。そのトークンが漏えいした場合、別のトークンを新たに発行できることさて、UDIDやUUIDはこれらの条件を満たしているでしょうか?そのトークンは、行使者しか知らないor作成できないものであることUDID(とadvertisingIdentifier)は、同一デバイス上のすべてのアプリが同一の値を得るため、「トークンを行使者しか知らない」という条件を満たすことはできません。Jailbreakすればデバイス自体のUDIDを書き換えることができるため、「トークンを行使者しか作成できない」という条件も満たしません。これらのことから、UDID(とadvertisingIdentifier)は認証トークンとしては使えないことが分かります。UUIDはその端末上のそのアプリ内でのみ利用されるため、セキュアに保存&通信する限りは「トークンを行使者しか知らない」という条件を満たします。identifierForVendorも、そのベンダのすべてのアプリがそれをセキュアに扱っている限りは、「行使者しか知らない」という条件を満たすものとして考えてよいでしょう。identifierForVendorはUUIDと比べて共有範囲が広く、それらがすべてデバイスから削除されない限りはリセットされない(lifetimeが長い)ため、UUIDに比べ、漏えいのリスクは高くなります。Tokenは、基本的にはそれを発行されたアプリにのみ渡され、他のアプリにその値が漏えいすることはありません。Serverのみ生成可能な文字列であり、攻撃者が有効なトークンを作成することはできません。Tokenは、「トークンを行使者しか知らない」「トークンを行使者しか作成できない」といった条件を満たします。Tokenは、Cookieに保存するなどのユースケースも想定されているため、ユースケースによっては必ずしも「トークンを行使者しか知らない」という条件を満たすわけではありません。そのためトークンに発行者の署名が付けられており、「トークンを行使者しか作成できない」といった条件を満たすようになっています(「トークンを行使者しか知らない」という条件を満たす使い方をすることも可能です)。そのトークンは、リプレイ攻撃ができないこと攻撃者が被害者のデバイスから送信されたある正常なリクエストの内容を傍受し、リクエストに含まれる認証情報をそのままコピーして利用することで不正にログインする攻撃手法を「リプレイ攻撃」といいます。認証情報自体が暗号化されていても、暗号化された結果が常に同一値に固定される場合、リプレイ攻撃を受ける可能性があります。リプレイ攻撃を防ぐには、「nonce」と呼ばれるワンタイムトークンを使う方式が一般的です。nonceを含んだリクエストに署名を掛け、リクエストを受けた側が一定期間内に同じnonceを含むリクエストを拒否することで、リプレイ攻撃を防ぎます。ところがかんたんログインは、リクエスト署名の利用などを想定した仕組みではありません。従って、かんたんログインの識別子としてUDIDやUUIDを利用しても、リプレイ攻撃を防ぐことはできません。かんたんログインを使いつつリプレイ攻撃を防ぐには、かんたんログインとは別にリクエスト署名の仕組みを実装し、nonceを利用できるようにする必要があります。リクエスト署名のための秘密鍵をアプリ自体に埋め込んでしまうと、攻撃者と被害者どちらのデバイスでも同じ鍵が利用されてしまい、攻撃者が容易にリプレイ攻撃に使える認証情報を得ることになるため、インストールごとに異なる鍵を配送する必要があります。なると鍵配送のために新たな認証の仕組みが必要になるため、OAuthのような仕組みが必要になるでしょう(それはもはや「かんたんログイン」といわれる、ユーザーが明示的なログインを行うことなく認証を完結させるという方式ではなさそうですね)。Token)もこの条件を満たしてはいません。Profileにはリクエスト署名が存在しないため、nonceを利用することもできません。Flowの場合は必須)にしています。Tokenは、「そのトークンは、リプレイ攻撃ができないこと」という条件を満たします。そのトークンは、書き換え攻撃ができないことUDIDは、前述のようにJailbreakにより書き換えが可能なため、この条件も満たしません。UUIDに関しては、それをセキュアストレージ(iOSの場合はKeyChain)に保存している限り、書き換えられる恐れはないでしょう。iOSのUserDefaultsのように保護されていないストレージ領域に保存された場合には、漏えいおよび書き換えの危険があります。Tokenについても同様です。Flowを利用する場合)ため、そのリダイレクトレスポンスを書き換えられる可能性もあります(トークン置換攻撃)。IDでログインには注意!」の章で紹介した脆弱性です。Clientが検証できれば、トークン置換攻撃を防ぐことができます。2.0自体にはそのような検証の仕組みは定義されていないため、別途、トークン検証の仕組みを用意する必要があります。Tokenは、トークンに発行者の署名付きで発行先が明記されているため、仕様通りにトークンを検証するだけでトークン置換攻撃を防ぐことができます。そのトークンが漏えいした場合、別のトークンを新たに発行できることUDIDは端末にひも付いているため、漏えいしたからといって別のUDIDに置換することは不可能です。端末上で生成されるUUID、identifierForVendorについても、漏えい後にアカウント情報を引き継いだまま該当ユーザーに別の値を割り振るには、それらの識別子以外の認証方法が必要になります。よってこれらを(明示的なログインやユーザー登録を伴わない)かんたんログインのために使う以上は、「そのトークンが漏えいした場合、別のトークンを新たに発行できること」という条件は満たしません。かんたんログインを維持したままこの条件を満たすことは不可能でしょう。Connectは、OAuthサーバがユーザーを認証できることを前提としているため、トークンが漏えいしても、古いトークンを破棄してもう一度ユーザーをOAuthサーバに送り、新たなトークンを取り直すことができます。Tokenは、「そのトークンが漏えいした場合、別のトークンを新たに発行できること」という条件を満たします。6.0から追加されたidentifierForVendorについても、「認証トークン」としての利用可能性を見てきました。結論としては、それらのいずれも「認証トークン」が果たすべき条件をすべて満たせるものではありません。それらを利用してかんたんログインを実現する限り、なりすましの危険性や漏えい後のアカウントリカバリが不可能であるなどの限界が見えてきました。一方で、現実問題としてユーザー登録による離脱率の上昇を抑えたいなどの理由で、それらの識別子を用いたかんたんログインを依然として選択するケースもあるかと思います。iOS上のゲームアプリなどでは、端末をまたげなかったり、アプリを消すとそれまでのデータがすべて消えてしまうなどの挙動に対する共通認識もある程度共有されているようです。いったケースにおいてまでかんたんログインの利用を否定するべきかどうかというと、筆者にはまだ疑問が残ります。いった場合にも、その選択によってどのようなリスクや制約条件が発生するのかはきちんと理解してほしいと思います。今回はUDIDのセキュリティ上の問題点を紹介しましたが、次回はUDIDのプライバシー上の問題を見ていきたいと思います。Evangelist。2.0のRubyライブラリを開発している。メールマガジンをご購読ください。Japanスマートジャパン3Dモデラボキャリア@IT自分戦略研究所エンジニアライフディルバートアプリITmediaねとらぼねこらぼついトピ!ITmediaはアイティメディア株式会社の登録商標です。