日向夏特殊応援部隊

俺様向けメモ

"OpenID: Single Sign-On for the Internet" を読んだ (1)

BlackHat USA (2007) で Eugene Tsyrklevich さんと Vlad Tsyrklevich さんがプレゼンした資料がオンラインで見れます。

で既に日本語でも紹介記事があります。
自分でも読んでみたので、逐一解説してみたり考えを書いてみたいと思います。
幾つかあるんで一個ずつピックアップしていきます。

Downloading an OpenID URL

通常 RP では OpenID を使った認証を提供する際に、ユーザー向けに何らかのフォームを用意します。ここは本来、そのユーザーが所有する Claimed Identifier あるいは OP Identifier を入力するべきフォームですが、そうではない文字列を入力した際に問題があるかもよと言う話です。

まぁこれはパスワード認証フォームとかでやっては行けないと言われてる、

  • そんな ID は存在しません
  • パスワードが間違ってます

的な、アタックに必要なヒントを与えるエラーメッセージとか丁寧に返してたりする場合に成り立つのかなと思います。

ポートスキャン

http://example.com:1/, http://example.com:2/, ..., http://example.com:8080/ などと言った物を試していって、

  • 接続出来なかった
  • 接続出来たけど discovery は失敗した

とかまだ出てたらそのRPの入力フォーム自体がポートスキャンの踏み台になっちゃう。

ローカル IP

http://192.168.1.123/show_profile.pl みたいなローカル IP 使って試す場合にローカルネットワークで何のアプリケーションが使われてるとかバレちゃったりする可能性がある。

loopback

http://localhost/ とかね。これはローカルIPと同様ですね。

Denial of Service attack

OpenID Authentication 2.0 にもちゃんとこの攻撃手法の項があります。(15.5. Denial of Service Attacks)
これは手前味噌ですが僕も訳しました。( 15.5. サービス拒絶攻撃 (Denial of Service Attacks))
和訳版の内容は保証しません、悪しからずw

一般的には不正なリクエストを相手に送って、その相手が提供しているサービスを利用不可能な状態にしちゃう攻撃手法ですね。DoSとかもそういう事なのかな?
spec では associate の際にOPが行う計算処理が重たいと言うのを利用して、その計算が行われるようなリクエストをガンガン投げて落とすと言う内容なんだけど、このプレゼンの内容では

  • 巨大なファイルを提供する URL
  • ハングする CGI

みたいな物を入力させて Denial of Service attack とするとあります。

http, https 以外の scheme

例えば file:///etc/shadow とかですかね。

対策

大前提として詳細なエラーメッセージは出さない

もう既に述べたけど、ヒントになるようなエラーメッセージを見せちゃダメです。

ポートスキャンへの対処

RP が特定ポートへの接続を行えたかどうかってのは大前提が守られていれば、悪意のあるユーザーはそれの正否を知る由も無いのですが、それでもそういった URL を入力される可能性はあります。
そもそも well known port としてそれぞれの scheme に割り当てられている port じゃないと受け付けないようにするとかでも良いのかも。
あるいは後手に回って、特定パターン (ポート番号変えただけみたいな) での試行が特定の期間で連続何回以上あったら、一時的にブロックとかそういう話になるんじゃないのかな。

ローカル IP

IPv4 - Wikipedia # 予約アドレス一覧 に見られるようなプライベートアドレスは除外で大丈夫かと。

loopback

Claimed Identifier ないしは OP Identifier としては discovery が出来る訳が無いので除外すれば良いかと。

Denial of Service attack

discovery フェーズでこの攻撃を成り立たせるには色んな方法が考えられるけど、特定の url 一つでコケるってのはお粗末な実装な気がする

  • まず HEAD なりで Content-Type を見るなりで不正なメディアタイプのリソースには GET しない
  • ってかそもそもアクセス時にタイムアウトを設ける

まぁ大量にアクセスされたらってなったら、これは一般的な DoS 対策の話になってくるんだと思います。

http, https 以外の scheme

正確には xri:// の可能性があるけど、これは URI じゃなく XRI だし、普通に resolution するだけなんでここでは問題にならない。
で、spec上は http or https じゃないとダメとあるんで、まともなライブラリなら弾いてくれるでしょう。

まとめ

この攻撃手法はそんなに脅威じゃないけど、最低限守るべき事柄として、

  • (攻撃者に対して) 親切なエラーメッセージを出さない
  • プライベートアドレスや loopback である localhost とかは除外対象にする (ライブラリ側でやってるか確認した方がいい)

などは徹底して、後は Denial of Service attack への対策 (IPで弾いたりとか) を行えばいいと思います。

追記 (2008-06-13T18:17:24+09:00)

つまるところ、OpenID: Single Sign-On for the Internet (PDF) で述べられているこの攻撃手法は、全然脅威じゃないです。

エラーメッセージ云々とか当たり前だし、プライベートアドレス云々は Perl のライブラリなら LWPx::ParanoidAgent を使うと思いますが、_bad_host() で、

my $haddr = unpack("N", $addr); # host order IP address
return 1 if
    ($haddr & 0xFF000000) == 0x00000000 || # 0.0.0.0/8
    ($haddr & 0xFF000000) == 0x0A000000 || # 10.0.0.0/8
    ($haddr & 0xFF000000) == 0x7F000000 || # 127.0.0.0/8
    ($haddr & 0xFFF00000) == 0xAC100000 || # 172.16.0.0/12
    ($haddr & 0xFFFF0000) == 0xA9FE0000 || # 169.254.0.0/16
    ($haddr & 0xFFFF0000) == 0xC0A80000 || # 192.168.0.0/16
    ($haddr & 0xFFFFFF00) == 0xC0000200 || # 192.0.2.0/24  "TEST-NET" docs/example code
    ($haddr & 0xFFFFFF00) == 0xC0586300 || # 192.88.99.0/24 6to4 relay anycast addresses
     $haddr               == 0xFFFFFFFF || # 255.255.255.255
    ($haddr & 0xF0000000) == 0xE0000000;  # multicast addresses

って感じでチェックもしてます。