Articles

GoogleのXSSゲームでXSSを学ぶ

GoogleのXSSゲームの解き方をステップバイステップで解説

Photo by Markus Spiske temporausch.J.

Google XSS Gameは、Googleが提供するXSSを実践するためのトレーニングプラットフォームです。 6つのレベルで構成され、各レベルでは、次のレベルに進むために、JavaScriptの警告を実行する必要があります。 各レベルでは、異なる問題が提供され、あなたは各レベルで異なるテクニックを使用してアラートを実行する必要があります。

それでは始めましょう。

https://xss-game.appspot.comに移動してください。 ここでGoogle XSS Gameが利用できます。

このようなページが表示されます。

Let me at ‘em! 9648>

First task : Hello world of XSS

virtual browser で xss payload を注入する必要があります。 toggle” リンクをクリックすると、ソースコードを見ることができます。

ソースコードを確認すると、それは python スクリプトで、関数
def get(self)内の 2 つの興味深い部分は

self.response.headers.add_header("X-XSS-Protection", "0")

query = self.request.get('query', '')
message = "Sorry, no results were found for <b>" + query + "</b>."
message += " <a href='?'>Try again</a>."

最初の部分は chrome XSS 監査をオフにして、ブラウザで XSS ペイロードを挿入できるようにします。

2番目の部分は、urlパラメータqueryの値が直接ボディに追加されることを示しています。 そこを突かなければなりません。

これは簡単なもので、検索ボックスに以下のいずれか(さらにもっとある)を入力して検索してみてください

<a href="javascript:alert()">Link</a>

<img src=X onerror="alert()">

<script>alert()</script>

といった感じです。 最初のものを使った場合は、alertを実行するためにLinkをクリックする必要があります。

素晴らしい!!! レベル1を無事クリアしました。

Second task : Persistence is the key

このタスクでは、記事を追加して警告を実行しなければならない。 このゲームでは DOM XSS ですが、実際のチャット/コメント アプリケーションでテストすると、格納型 XSS になります。

それでは、ソースと以前のメッセージも見てみましょう。 それが私たちの鍵です。

ソースを点検して確認してください。 これが投稿の表示方法です。

投稿がどのフィルターも通過していないことがわかります。

<a href="javascript:alert()">Link</a>

<img src=X onerror="alert()">

このように、どのような方法であっても利用できます。 あなたはレベル2を完了しました。

Task 3 : That sinking feeling

これは今までの2と全く異なるものです。 ここでは、window.location.hash.について学ぶ必要がある。これは、#記号の後に来る部分で、ページ内ナビゲーションのために使われる。

このコードの中で興味深いのは、

var html = "Image " + parseInt(num) + "<br>";
html += "<img src='https://medium.com/static/level3/cloud" + num + ".jpg' />";

numwindow.location.hashの値を持っていて、2箇所で使われていることです。 まず、parseInt関数の内部で使用されるので、ペイロードはそこで動作しません。 しかし、次の行では、生のデータが使用されます。

そこでシングルクォート ' を閉じ、ペイロードを注入する必要があります。

#

#の後の' 'の中に任意のペイロードを試すことができます。

1' onerror='alert()

1'><img src=X onerror="alert()">'

1'><script>alert()</script>'

1'><a href="javascript:alert()">Link</a>'
などなど、素晴らしいです。

Task 4 : Context Matters

タイマーの時間を入力するスペースがありました。

ソースコードを確認してみましょう。

timer.html に、この行があります。

<img src="https://medium.com/static/loading.gif" onload="startTimer('{{ timer }}');" />

我々は {{ timer }} 式で悪用しなければなりませんが、これは onload イベントに対するイベント ハンドラである関数 startTimer(''); 内に配置されています。 注意すべき主なポイントは、HTML のイベント ハンドラ属性は複数のコールバック関数を受け入れるということです。 値がparseInt関数を介して渡されなかった代わりに、生データが使用されていることに注意してください。 そこで、');を追加して関数を閉じ、alertを注入することができます。 インラインで使用されているため、alert();を注入することはできません。

そこで、パターンを壊さないように追加する必要があります。
alert('を追加すれば十分です。

それで、ペイロードは

3');alert('

タイマーの開始ボタンをクリックするとアラートが実行されて、このレベルは完了です。

次のタスクに進む。

Task 5 : Breaking Protocol

ホームページでは何も注入する方法がないですね。 あるのはリンクだけです。

ここで、ペイロードを注入するための 2 つの場所を見ることができます。 入力ボックスは、電子メールを入力する場所であり、他の場所に反映されないことを期待します。 では、1つ目の場所に行ってみましょう。 url.

現在のページ、つまり signup.html のソースコードを調べてみると、

<a href="{{ next }}">Next >></a>

という行があり、ペイロードを注入するには絶好の場所であることが分かります。 ペイロードはaタグ内のhref属性の値として設定されます。 もし、javascript:alert()を追加することができれば、ペイロードを実行することができます。 では、nextの値はどうなっているのでしょうか。 このページには何も見当たりません。 どこを探せばいいのでしょう?

Python コードで解決します。 level.py をチェックすると、

if "signup" in self.request.path:
self.render_template('signup.html',
{'next': self.request.get('next')})

そこで、url の next の値が使用されることが分かります。

urlのnextの値をconfirmからjavascript:alert()に変更すると、最終的なurlは

Now clicking on Next >> in the page will trigger our payload.

We now completed level 5. And 1 level remains.

Task 6 : Follow the 🐇

There is a path to a js file in the url.

Let’s inspect the source code. In page index.html, you can see a function includeGadgetのようになり、関数本体の中に以下のコードがあります。

ここで、dataのurlを試してみましょう。

データのurlはdata:{type},content

という形式なので、#以降の値を

data:application/javascript,alert()

または

data:text/plain,alert() に変更すればalertを実行できるはずです。

「ゲーム」を解く動画はこちら