Seiichi Yonezawa

“How creativity is helped by failure”

2017-03-22

会員情報の移行

現在の案件では、某求人サイトの会員情報をRailsに移行するために、データベースの中身を見る機会がありました。そのシステムは現在も稼働中なのですが、これから移行するのはDeviseで書かれたシステムで、旧サイトはphpで構築されていたのですがパスワードは暗号化せずにテキストのまま保存してありました。パスワードのハッシュ化はDeviseの関数を利用したかったので単純なSQLでの移行をせずに、1件ずつインスタンスを作成し、save!していくことになりました。今回は実際に私が作業したというよりは、半ばペアプログラミングで横から作業の様子を眺めていたのですが、そうある経験ではありませんので残しておこうと思います。

真っ先にぶち当たった問題はパスワードが4文字に設定しているユーザーの存在でした。銀行の暗証番号じゃあるまいし、そんな短いパスワードでいいのかと思ってしまいますが、確かウェブサイトで使われている最も多いパスワードがpasswordだったということも考えると別に珍しい話でもないのかもしれません。また、驚くべきことに4文字以内のユーザーも少なからず存在していたようで、今でこそパスワードは英数字に記号や大文字を混ぜないとエラーを出すサイトも増えてきましたが、この案件に限らず当時はパスワードもとりあえず設置しておけばよいくらいの認識だったことは想像に難しくないかもしれません。

それ以上に残念なのは、会員のインポートを行うにあたって今回の方針ではユーザーのパスワードは原則そのまま移行して、ログイン後も特にパスワードの変更を求めないそうです。ということは、遠い昔に求人サイトを利用して、そのまま放置しておいたとしても、丁寧に名前やアドレス、そして短いパスワードはそっくりそのままデータベースに残り続けるということなのです。これは求人サイトに限らず、ネット通販や宿泊サイト等でも起こりうるし、会員情報を求めるサイトに対してはほぼすべてに起こりうる問題だと思います。Tim Berners-Lee: I invented the web. Here are three things we need to change to save itという記事ではもう少し掘り下げて説明しています。

若干逸れてしまいましたが、会員には4文字以内のパスワードもいれば、逆に32文字以上のパスワードを使う人もいました。ただ、今回の移行には明確にパスワードは20文字までと定められているので、32文字のパスワードも通さなければなりません。これがいわゆるdegradeなので申し訳なくも思うのですが、その人のパスワードはすべて[a-z]{32}で表現されていました。ピンポイントに総当たりで攻撃される場合は歯が立たないかもしれませんが、たくさん会員がいる場合は案外有用かもしれませんね。また、おそらく最も強固なパスワードはカタカナのみのパスワードでした。入力する手間が多そうですけれども、さすがにハッカーがカタカナのパスワードを想定しないと思います。

パスワード問題を回避したと思いきや、今度はメールアドレスの問題が浮上しました。というのも、Deviseは特に設定しなくともメールアドレスを正規表現で簡易的にチェックしてくれるのですが、その正規表現が緩すぎて以前メールが送信できないという問題がありました。そのため、独自に強固な正規表現を使って[email protected]\softbank.jpというメールアドレスを弾くようにしたのですが、上述したパスワードの存在があるので当然もっとひどいメールアドレスが運悪くそのまま登録されていたのです。

最初はメールアドレスの字数制限を大幅に超えるアドレスでした。パスワードのように、メールアドレスも20文字に収まらないアドレスは当然たくさんあるわけで。これは逆にこれから稼働するサイトは大丈夫なのかなぁと思いつつも制限をゆるくしました。しかし、続いて登場したのは同じく20文字以上のアドレスでしたが、これがなぜか通らない。その時使われていた正規表現は/\A[^@\s]+@[^@\s]+\z/これでした。意味合い的には「@と空白以外の文字列が含まれていない文字の連続が@で区切られている」つまり、メールアドレスに空白が含まれていて、なおかつそのアドレスで会員登録ができてしまったということです。いつ頃登録されたものかはわかりませんが、おそらくこれを登録した本人もそのまま放置していることを願いつつ。なぜならメールアドレスは後から変更できない仕様なのです。

結局Deviseの設定を/.+/このように変更して、モデル側に2通りのvalidates :emailを設定することになりました。片方は新規会員用で、こちらは従来のアドレスで登録し、移行した会員は更新時にのみチェックすることに。というのも、スペースが含まれているものはまだ可愛い方で、@すら含まれていないメールアドレスも存在していたからです。結局いくら優れたライブラリを利用したり、優れたサイトがどうあるべきか研究していても、いざ使う側がそのハードルを下げれば下げる程にシステムそのものがだめになっていく感じがします。まだそこまで大きくはありませんが、セキュリティ的なリスクも、こういった不要なif文の抜け穴から生まれるのかもしれません。ただ残念ながら私にはそれを止める権限がありませんのでこのサイトを利用する会員は気の毒だなぁと思います。