tl;dr
- OmniAuth を使う場合、まずはユーザーを
/auth/:provider
のような URL に誘導すると思います。 - このパスで GET リクエストを受け付けることは、セキュリティの観点から推奨されていません。
- 具体的には、ユーザーが意図しないうちに、意図しない外部アカウントを紐付けてしまう危険性があります。
- 代わりに POST を受け付けるようにしましょう。
どんな問題が発生するの?
前提
Web サイト A と B が存在するとします。
Web サイト A は OmniAuth を使って、「B のアカウントでログイン」のような機能を実装しています。そして /auth/site_b
で GET リクエストを受け付けています。
アリスとマロリーがいるとします。アリスは被害者、マロリーは攻撃者です。
アリスは A のアカウントを持っていて、A にログイン済みですが、B のアカウントは紐付けていません。マロリーは B のアカウントを持っていて、あらかじめ A に対する認可を済ませてあります 1 。
攻撃開始
さて、マロリーの攻撃が始まります。
アリスはマロリーの攻撃により、マロリーのアカウントで B にログインした状態になってしまいました 2 。さらに続けて、マロリーは A の /auth/site_b
に GET リクエストを投げされられてしまいました 3 。
アリスは B の認可画面にリダイレクトされますが、アリスは(マロリーのアカウント)で B にログインした状態なので、ID/PW を聞かれることはありません。さらに、マロリーは既に A に対する認可を済ませてあるので、認可画面も表示されません。ただちに A の /auth/site_b/callback
にリダイレクトされます。
結果的に、 アリスの A アカウントにマロリーの B アカウントが、何の確認もなく紐付けられてしまいます 。言い換えると、マロリーがアリスの A アカウントに対して全権を手に入れてしまったのです。
この問題には CVE-2015-9284 という名前がついています。
何が原因なの?
ひとつは、アリスがマロリーの B アカウントでログインさせられてしまったことです。これは単に B の脆弱性で、今回のメインテーマではないので省略します。
もうひとつは、A の /auth/site_b
が GET リクエストを受け付けていることです。
もしここが POST だけを受け付けて、なおかつ CSRF 対策が有効になっていれば、A にログインする前に必ず A の画面上で何らかのインタラクト(ログインボタンを押すなど)をユーザーに求めることができます。GET だと CSRF 対策ができないので、ユーザーに意識させないまま OAuth 連携処理を完了できてしまうのです。
どうすればいいの?
詳細は https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284 に載っているので、それに従えばよさそうです。おおざっぱにいうと、 omniauth-rails_csrf_protection という gem を入れた上で、 /auth/:provider
への GET リクエストを全て POST に置き換えていく、という流れになります。omniauth-rails_csrf_protection は、Rails に搭載されている CSRF 対策と同じメカニズムを OmniAuth の Rack ミドルウェア層に導入する Gem のようです。
重要なのは、この脆弱性が OmniAuth のアップデートによって直るたぐいのものではなく、我々 OmniAuth ユーザー側の対応が必要な点です。自分の Web サイトで /auth/:provider
への GET リクエストが要件上必須かどうか検討して、必要なければ排除してしまいましょう。
余談
この問題のことを知ったのは、dependabot が作った PR がきっかけでした。
security
ラベルが付いていたので、最初はこの v1.9.1 で脆弱性が直ったのかな?と思ったのですが、v1.9.1 のリリースノートにも「脆弱性を直した」とは書かれていません。どうやら、単に GitHub Advisory Database の Affected versions
の更新が遅れているだけのようです。v1.9.1 でこの脆弱性が直っているわけではありません。
参考
- https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284
- https://github.com/omniauth/omniauth/pull/809
- https://github.com/cookpad/omniauth-rails_csrf_protection
- https://github.com/advisories/GHSA-ww4x-rwq6-qpgf