2010-04-05 2010-04-05
●JavaアプレットのDNSリバインディングはJRE側で対策済みだった
Black Hat Japan 2007における金床氏のプレゼンテーションや金床本で、Javaアプレットに対するDNSリバインディングの手法が説明されている。ここしばらく、その追試を行っていた。結論としては、金床氏の方法にはJRE側で対策がとられていたので報告する。
金床氏が報告しているDNSリバインディングの手法とは以下のようなものだ(金床本に説明されている方法)。
- 被害者のユーザにワナのページをPROXY経由で閲覧させる
- ワナのドメイン(FQDN)に対するIPアドレスを変更する
- ワナページ上で数秒〜数十秒のちにJavaScriptによりJavaアプレット用のHTMLをレンダリングする
- JREがアプレットをPROXY経由で*1ダウンロードする
- アプレットのダウンロード時点で既にDNSレコードは書き換わっているが、PROXYがDNSキャッシュしているため、アプレットは正常にダウンロードされる
- アプレットからワナサイトのFQDNの任意のポートに対してSocket通信する。
- 既にIPアドレスは書き換わっているので、プライベートアドレスに対して任意のSocket通信ができることになる。
このように、攻撃が成立すればとても凶悪な攻撃となるのだが、最近のJREでは以下の方法で対策されているようだ。
- アプレットがPROXY経由でダウンロードされた場合、アプレットからのSocket通信は全てクロスドメイン通信と扱われる
このような挙動に変わったバージョンを調べたところ、Java SE 6 update 3以降であることが分かった*2。すなわち、Javaアプレットの金床方式によるDNSリバインディングが成立するバージョンは以下の通りである。
- J2SE1.4.xの全てのアップデート
- J2SE5.0の全てのアップデート
- Java SE 6のUpdate2以前
そして、Java SE6 Update3以降で、クロスドメイン通信になった場合の挙動は、JREのバージョンにより異なる。Java SE 6 update 10より前のバージョン(Update3〜7)だと、Socketでダイレクトにアクセスしようとするとエラーになる。一方、Java SE 6 update 10以降のバージョンでは、アクセス先のcrossdomain.xmlを参照して、その内容に従う。このあたりの挙動は、「次世代 Java(TM) Plug-In テクノロジのリリースノート (JDK 6u10)」を参照されたい。
一方、アプレットが直に(PROXYを経由せずに)ダウンロードされた場合は、アプレットの置かれたFQDNに対してSocketによる任意ポートへの通信が可能だ。この場合は、DNSリバインディングが懸念されるところであるが、Javaの強固なDNS Pinningにより、アプレットダウンロード時のIPアドレスが永続的に保持されるので、DNSリバインディング攻撃はできない。
したがって、金床氏のプレゼンテーション資料には、Java版DNSリバインディング対策が色々書かれているが、その後Java側で対策がとられたことを考慮すると、ユーザが取るべき最善の対策は以下だろう*3。
- JREを最新のバージョンにアップデートする
J2SE5.0以前のバージョンは既にEOLになっているし、DNSリバインディング対策もとられていないことから、使うべきではない。
また、Socketクラスではなく、URLクラス等HTTP系のクラスを使う場合は、PROXY経由の有無にかかわらず元FQDNとの通信は可能である。URLクラスを使う場合は、アプレットダウンロード時の設定に従い、PROXY経由となるか否かが決まる。URLクラスで、PROXY経由しない場合は、JavaのDNS Pinningが有効となり、DNSリバインディングはできない。一方、PROXY経由の場合は、PROXY側のDNS Pinningが問題となる。PROXYによるDNSリバインディング対策については稿を改めて説明する。
*1 Javaの設定にもよるがデフォルトはブラウザの設定をそのまま利用するので、PROXY経由となる
*2 Java SE 6 update 3がリリースされたのが2007年10月3日、金床氏のBHJでのプレゼンテーションが2007年10月25日だったので、BHJのプレゼンテーション時点でJRE側の対策がなされていたことになる。ただし、update 3のリリースノートを読んでも、このような対策がなされていることは読み取れなかった。おそらく金床氏もupdate 3で対策されたとは明確には分からなかったのだろう。金床氏のJavaアプレットによるDNSリバインディングのデモページには「Does not work on JRE1.6.0_03 or later」と明記されている。
*3 今時Javaアプレットなど使わないというのであれば、あわせてJavaアプレット(プラグイン)を無効にするというのもあり。その場合もJREのバージョンは最新にすべきだ。
FYIヽ(´ー`)ノ<br>http://sunsolve.sun.com/search/document.do?assetkey=1-26-103078-1<br>http://www.jumperz.net/index.php?i=6&threadId=33671191642815452
>おそらく金床氏もupdate 3で対策されたとは明確には分からなかったのだろう。<br><br>いえいえ、ちゃんとわかってましたYo!当日のプレゼンでは口頭で説明しました。BHはプレゼン資料提出がかなり早いんで訂正できなかったんですよ。
金床さん、コメントいただきありがとうございました。<br>sunのドキュメントはまだきちんと読めていないので、読ませて頂きたいと思います。<br>ただ、生Socketが使えるDNSリバインディングは、プラグイン側の問題として対処が進んでいるようですね。