PHP+MongoDBのセキュリティ


大量のユーザを抱えるウェブサイトは、インメモリのKVSとしてRedisやMemcachedを使うなどしてパフォーマンスを上げていると思う。
NoSQLのデータベース、MongoDBも注目されていた。


MongoDBは$neのようなオペレータを使うのだが、
PHPだとこのオペレータが埋め込んであるURLをそのまま解釈してしまう。
PHPで書かれたlogin.phpというページがあり、それがMongoDBでアカウント管理を行うログインページになっていたとする。

http://www.(省略)/login.php?user[$ne]=foo&password[$ne]=bar

こんな風にアクセスされた時、userやpasswordのフォームに"あるもの"が埋まった状態でボタンが押されたかのように処理される。

find(array(
   "user" => array("$ne" => foo),
   "password" => array("$ne" => bar)
));

恐らくはこのように解釈される。$neは"等しくない"ものを指示するので、foo以外の正規userとbar以外の正規passwordの組み合わせに対して
組み合わせが正しいか判定してしまうので、まるで正しいuserとpasswordが埋まっていたかのように自動的にログインに成功してしまう。


他にも、セッション管理にMongoDBを使っている場合、同様にして$neオペレータとの組み合わせをセッションIDに渡す事で
ログイン済みユーザになってしまう場合がある。


PHPRubyなど、動的型付け言語とMongoDBの組み合わせを行う場合、想定外のデータ型に対する対処が必要だ。
動けばいいや、が一番不味いが、テストしてバグが収束しただけでもダメで、セキュリティのペネトレーションテストも今の時代は重要なことである。