誰にでも分かる易しい情報漏洩のしかた - 基礎編

最近peingにてTwitterのトークンなどが流出する問題が発生しました。しかしこれは何も知らなければ簡単に作り出せてしまう脆弱性です。具体的にどのようにしてこの情報漏洩が発生したのか、そしてどのようにして防ぐことができるのかのざっとの基礎について書いてみます。(ちなみに特に続きの記事はありません)

そもそもなぜ情報漏洩したのか

ユーザーの情報を表示する昔ながらの方法

例えば下記のような構造のusersテーブルがあったとします。

カラム 役割
id ID
name 名前
twitter_token TwitterのAccess token
twitter_secret TwitterのAccess token secret

Webサービス上にてユーザーの名前を表示したい場合、例えばPHPのLaravelであれば下記のようにして表示します。

お名前:{{ $user->name }}

データをMySQLから取得後、メモリ上にはTwitterのトークンなどが存在しますが、ここではテンプレート上で名前しか表示していないので問題はありません。わざわざトークンを表示する、ということもないと思うのでこういった場合には問題になりません。

ユーザー情報をAPIで取得する場合

最近はフロントエンドとバックエンドが分かれることが多くなり、直接テンプレート上に表示する形ではなく、バックエンドから情報をJSON形式に変更してフロントエンドに伝える、という形が多くなりました。

例えばユーザー情報をPHPのjson_encodeでJSONに変換すると、下記になります。

{  
  "id": 154,  
  "name": "taro",  
  "twitter_token": "weojwaiofj09a9aw9efjaw0efoawj2j3io2f",  
  "twitter_secret": "ojweiofjaoiejfajewkljfaoiwejf"  
}

当然のことながら、表示したいところだけではなくユーザー情報全てがJSONに含まれています。これを送信するため、ChromeのDev Tool等では丸見えになります。こういったことが今回の原因の一つになっています。

情報漏洩しないための対策

送信する情報を制限する

古き良き形と同様、単に表示したい情報をフィルタリングすればよいだけです。

データベースから取得する際に制限する

例えば、MySQLからデータを取得する場合、

SELECT * FROM users

のようにして全部取得するのではなく、

SELECT id, name FROM users

のように必要な情報だけを取得するようにします。メモリの無駄な消費も避ける事ができます。

アプリケーションフレームワーク側で制限する

例えばLaravelの場合、モデルの設定でJSON化する情報を設定することができます。

protected $visible = ['id', 'name'];

上記のようにすればIDと名前しか表示されませんし、

protected $hidden = ['twitter_token', 'twitter_secret'];

上記のようにすれば隠したいカラムを指定することができます。

Railsの場合もto_jsonに:only:exceptを指定することができます。

Goの場合、構造体に対してJSONの出力方法を指定する形になります。

type User struct {  
    Id int                   `json:"id"`  
    Name string              `json:"name"`  
}

設定は省略できますが、大文字そのままで使うということもあまりないと思うのでだいたい設定するのではないかと思います。なので設定中に「あれ、tokenってJSONに含めていいんだっけ…?」と勘のいい人であれば気づくことができます。このようにセキュリティをしっかりするためにわざわざちょっと面倒な言語やフレームワークを使う、という選択肢もあるのではないかと思います。

もちろん知識があれば選択は自由ですが、それでも人間が作っているものですのでいつも不安は残ります。

そもそも情報漏洩しても問題ないデータ構成にする

今回の件でせせりさんもツイートされていましたが、人為的なミスは起こる可能性がありますので、その場合にも問題ないデータ構造にしておく、ということも重要です。

例えば今回の例であればIDと名前はusersテーブルに入れておき、Twitter関連の情報はsocialsテーブルとして分けて入れておく、という具合です。これであればたとえusersテーブルのJSON生成方法をちゃんと設定しなかったとしてもTwitterのトークンが漏洩するということはありません。(元々せせりさんはこのように作っていたらしいですが、サービス譲渡後に変わってしまったようです)

まとめ

このように、正直情報漏洩は非常に簡単に行うことができますので、恐らく漏洩しているアプリは現時点でも非常に多いのではないかと思います。今回の騒動を見てダサいとか、対岸の火事だとか思わず、良い機会なので改めて自分で作っているサービスがあれば見直してみたり、セキュリティに付いてもっと深く調べてみると良いと思います。