ケース3:ユーザーIDそのものをクレデンシャルとして利用

尾上良範氏(以下、尾上):ケース3です。ここからはスマホアプリの事例となります。まず左側にあるのが被害者のスマホアプリです。ネイティブアプリとしてスマホアプリがインストールされています。yoursite.comというのはそのネイティブアプリのバックエンドのサーバーです。

まずどういった操作が行われるのかというと、スマホアプリにログインするためにLINE Loginのサイトとやり取りをしてログインします。アクセストークンなどをスマホアプリは取得します。アクセストークンを使ってユーザーIDなどを取得できるんですけど、そのあとです。そのあとに何をするかというと、ここではスマホアプリはバックエンドのyoursite.comのサーバーに対してこのようなリクエストを送っていたとします。こちらもこれだけ見たら必ずしも脆弱性があるわけではないですが、怪しいところがあります。

お気付きの方もいるかもしれませんが、ここにユーザーIDのようなものが含まれてしまっています。これ自体は問題ではないのですが、もしこれだけでユーザーをバックエンドのサーバーで認証しようとしていると、非常に問題があります。たとえここの通信経路が暗号化されていたとしても非常に問題です。

ケース3:適当なユーザーIDで攻撃する

攻撃者はどのように攻撃するかというのを説明していきます。まずは攻撃者が攻撃者自身のスマホとスマホアプリでログインを試みます。そうすると攻撃者のユーザーIDというのを攻撃者は取得できます。先ほどと同様に正常のアプリであるかのように偽装して、まったく同じリクエストをバックエンドのサーバーに攻撃者は投げます。このときにユーザーIDのところを適当な文字列で置き換えます。

ここではAの羅列としていますが、このAの羅列のIDがたまたま正しいIDであった場合は、攻撃者は簡単に被害者に成りすましていろいろな操作を行うことができてしまいます。

ここは補足ですが、LINE Loginの場合は、実際にこの攻撃が成立する可能性は低いです。というのもLINEのユーザーIDは十分にランダムな値となっているので、適当な値を入れたからといってそれが正しい値になる確率はかなり低いです。

もう1つあります。LINEのユーザーIDは、いわゆるPPIDという体系で発行されています。これはどういったことかというと、外部のサービスの提供者Aに対して発行するユーザーのIDと、Bに対して発行するユーザーのIDというのが、たとえそれが同じユーザーを表していても、違う文字列として発行されています。ですので、例えばAが管理しているWebサイトで情報漏洩したユーザーIDというのは、Bが管理しているWebサイトでは使うことができません。

ただこれだけではもちろんリスクがまったくないとは言い切れません。実際に、弊社ではありませんが、ユーザーIDが連番となっているようなソーシャルログインのサイトなどもありますので、注意が必要です。

ケース3の対策:ユーザーIDを認証情報として使わない

ではどのように対処すればいいのかというと、まずはユーザーIDそのものを認証情報としてやり取りするのはやめましょうということです。代わりにアクセストークンやIDトークンなどを使えばいいということになります。ただこれだけでは十分ではありません。なぜかというのを次のケース4で説明していきます。

ケース4:バリデーションなしのトークン利用

こちらは先ほどと同じような流れですが、2番のところのスマホアプリからバックエンドのサーバーにアクセスするところのリクエストヘッダーが違います。先ほどはユーザーIDが直接入っていたのがここではAuthorizationヘッダーで、アクセストークンを入れています。これは何が悪いでしょうか。

このリクエスト自体は実際には悪くありません。yoursite.comでするべき処理が1つあります。どういうことかというと、ここでバリデーションが必要になります。では攻撃者がどのようにこの流れを悪用するのかというのを説明して、どうしてバリデーションが必要なのかということを解説したいと思います。

まず真ん中に今まで出てこなかったサーバーの絵が描いてあるかと思いますが、攻撃者が用意した一見無害なんだけど実は危険なサイトです。

まずは被害者がLINE Loginの機能を使ってスマホアプリにログインをしようとします。この際のスマホアプリというのは攻撃者が用意した一見無害なアプリ、あるいは攻撃者に乗っ取られてしまった第三者のアプリかもしれません。そうすると攻撃者のサイトにアクセストークンが渡ります。こちらは一見無害なアプリを装っているので、必要最低限の権限の許可を求めるだけのサイトのことも多いかもしれません。そうするとユーザーは簡単に同意してしまいます。

では次に攻撃者は何をするかというと、それとはまったく関係ないyoursite.comに対して2番で不正に取得したアクセストークンを送ります。もしこれでyoursite.comがトークンの検証を行っていない場合、これはそのまま使えてしまいます。これがそのまま使えるということはこの被害者のユーザーIDなどが取得できてしまうことになります。

検証していないので、yoursite.comがこれは被害者からのリクエストだと認識してしまうことになります。被害者としては当然なりすまされていて、しかも1番のところで必要最低限の権限しか同意していないはずなのに、3番のところではyoursite.comの機能というのを成りすまされて使われてしまうことになります。

ケース4の対策:トークンをバリデーションする

対策としては、ここではLINE Loginの機能を呼び出す前に必ずトークンのバリデーションをしましょうということになります。バリデーションの方法なんですけど、LINE Loginではアクセストークンの検証用のAPIを用意しているので、アクセストークンを使っている場合はこちらを呼び出していただくことになります。

使い方はそれほど難しいものではありません。curlコマンドの例が真ん中に出ていると思いますが、APIに対してクエリパラメータでアクセストークンを送ると、もし問題がある場合はエラーになりますし、問題がない場合はアクセストークンに含まれている情報の一部が返ってきます。

ただこれだけではだめで、クライアントIDを検証してください。これは何かというと、みなさんがLINE Loginなどを利用するときに発行されたサービスを特定するためのIDです。こちらを検証しないと先ほどの例のように、他のサービスに発行されていたアクセストークンを使えてしまうことになるので、必ずこの検証が必要です。弊社のDevelopersサイトにAPIリファレンスが載っていますので、詳細につきましてはそちらも見ていただければいいかなと思います。

IDトークンを使った認証情報のやりとりの場合

ここまではアクセストークンの例で説明しましたが、IDトークンを使って認証情報のやり取りをすることもできます。この場合もIDトークンを偽装されないように、IDトークンの検証を行う必要があります。IDトークンについてはIDトークンに付いているシグネチャなどをみなさんで独自に検証することによってバリデーションを行うこともできます。

具体的な方法というのは今表示している画面のURLに記載はしているんですけど、そこそこ複雑でおそらく初めてやる方というのは多少時間がかかるんじゃないかなと思います。こういった検証の支援をしてくれるライブラリが各言語にあるんですけど、使い方がわかりづらくてハマることも多いです。

実際に初めて私が触ったときも使い方がわからないということもありましたし、他の言語のライブラリを使っている方から「うまく動かないんだけど」という問い合わせを社内で受けたこともあります。ですのでLINE Loginとしてはこちらも検証のための便利APIを用意しています。

こちらもcurlコマンドの例を載せているんですけど、使い方はそんなに難しくはありません。IDトークンとクライアントIDをPOSTのパラメータで送ります。問題があればエラーが返りますし、そうでない場合はIDトークンがデコードされて、含まれている情報が返ってきます。

本来であればクライアントのIDをここで検証する必要がありますが、このクライアントのIDの検証を忘れる方も多いと思うので、このAPIではあらかじめクライアントIDをパラメータとして受け取って、LINE Loginのサーバーサイドで検証することにしています。こちらもAPIリファレンスがDevelopersサイトに載っているので詳細は見ていただければいいかなと思います。

ポイントを押さえれば脆弱性は防げる

今回の発表はここまでですが、説明してきた通り、LINE Loginなどのソーシャルログイン機能というのは大変便利なんですけど、私たち開発者の実装ミスによってユーザーに多大な迷惑をかけてしまう可能性があります。実際に今回解説したような脆弱性を見かけることがよくあります。ただこれらの脆弱性というのは、説明してきた通り、ポイントを押さえれば防ぐことができるものです。

今回の発表が便利かつ安心なWebサービスやアプリの開発に役立てば、大変うれしく思います。ご清聴ありがとうございました。