最近peingにてTwitterのトークンなどが流出する問題が発生しました。しかしこれは何も知らなければ簡単に作り出せてしまう脆弱性です。具体的にどのようにしてこの情報漏洩が発生したのか、そしてどのようにして防ぐことができるのかのざっとの基礎について書いてみます。(ちなみに特に続きの記事はありません)
例えば下記のような構造のusersテーブルがあったとします。
カラム | 役割 |
---|---|
id | ID |
name | 名前 |
twitter_token | TwitterのAccess token |
twitter_secret | TwitterのAccess token secret |
Webサービス上にてユーザーの名前を表示したい場合、例えばPHPのLaravelであれば下記のようにして表示します。
お名前:{{ $user->name }}
データをMySQLから取得後、メモリ上にはTwitterのトークンなどが存在しますが、ここではテンプレート上で名前しか表示していないので問題はありません。わざわざトークンを表示する、ということもないと思うのでこういった場合には問題になりません。
最近はフロントエンドとバックエンドが分かれることが多くなり、直接テンプレート上に表示する形ではなく、バックエンドから情報を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のトークンが漏洩するということはありません。(元々せせりさんはこのように作っていたらしいですが、サービス譲渡後に変わってしまったようです)
このように、正直情報漏洩は非常に簡単に行うことができますので、恐らく漏洩しているアプリは現時点でも非常に多いのではないかと思います。今回の騒動を見てダサいとか、対岸の火事だとか思わず、良い機会なので改めて自分で作っているサービスがあれば見直してみたり、セキュリティに付いてもっと深く調べてみると良いと思います。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント