実戦形式で学ぶホワイトハッカーの技術

初心者向けのEthical Hacking講座です。

XSS(クロスサイトスクリプティング)

では実施にWebアプリケーション(以後:Webアプリ)を攻撃してみましょう。
まずはWebアプリの一番上にある「XSS(クロスサイトスクリプティング)」から行います。

XSSクロスサイトスクリプティング)とは、Webアプリの脆弱性の1つで、攻撃者が悪意のあるスクリプトを注入し、他のユーザーのブラウザでそのスクリプトを実行させるものです。攻撃者は被害者のセッション情報を奪取したり、不正な操作を行わせたりすることができます。

XSSは以下の3つの種類に分けられます。

1. Stored XSS(蓄積型): 攻撃者は悪意のあるスクリプトをWebアプリのデータベース上に永続的に保存します。コメントや投稿のような、ユーザーが生成するコンテンツを介すことで可能となります。その後、そのページを見る全てのユーザーに対してスクリプトが実行されます。

2. Reflected XSS(反射型): 攻撃者はURLの一部として悪意のあるスクリプトを含め、そのリンクをクリックしたユーザーのブラウザ上でスクリプトを実行させます。反射型XSSは、メールやWebサイト上にあるリンクを介して実行されます。

3. DOM-based XSS(DOM型): 攻撃者は悪意のあるスクリプトを利用して、WebページのDOM(Document Object Model)を操作します。DOMは、ブラウザがWebページの構造を理解し、それと対話するためのプラットフォームとAPIの集合です。攻撃者は、ウェブページの構造や内容を動的に変更するためにDOM型XSSを利用します。

今回実践的に学ぶのは反射型XSSです。個人的な感覚ではXSSの中で、反射型XSSに一番遭遇していると思います。

ではKali LinuxのブラウザからWebアプリにアクセスしましょう。
本カリキュラムのXSSではBurp Suiteを使う必要はありませんので、お好きなブラウザを起動してください。
僕はBurp Suiteのブラウザにて操作します。(ブラウザによっては一部XSSへの対策をしていることがあるので、Burp Suiteのブラウザがおすすめです。)

XSS(クロスサイトスクリプティング) - Level1

トップページより「XSS(クロスサイトスクリプティング) - Level1」をクリックしてください。
すると「2乗計算プログラム」という画面が表示されたはずです。

2乗計算プログラム

攻撃する前に通常の動作を確認しましょう。

例えば3という数字を入れてみます。すると2乗された数字9が表示されます。

3の2乗

他の数字で試してみても、全て2乗されて出力されることが分かります。
気づいたかもしれませんが、2乗された数字だけでなく入力した数字も同時に画面に出力されています。
サイバーセキュリティに関わる人間は必ずここでXSSがある可能性を疑います。

次に一度「hello」という文字列を入力してみましょう。

helloの2乗?

もちろん文字列「hello」を2乗することは数学的に不可能ですから、2乗された数字ではエラーっぽいものが確認できます。(NaNはNot a Numberの略です。)
しかしながら、入力した数字として「hello」が出力されています。
つまり数字でなくても画面上に入力した文字列を出力できることが分かりました。

では一度下記の文字列を入れてみましょう。

<h1>hello</h1>

すると「hello」が大きな文字で表示されたことが分かります。

<h1>hello</h1>

これはいったいどういうことでしょうか?
先ほど入力した文字列は「HTML」と呼ばれるものです。

HTMLは「HyperText Markup Language」の略で、Webページを作成するためのマークアップ言語の1つです。HTMLはWebページの構造を定義し、テキスト・画像・リンク・フォームなどの要素を配置するためのタグを提供します。
HTMLについては下記記事が参考になります。
udemy.benesse.co.jp

どんなWebサイトであってもページソースを見ることができます。
実際に「2乗計算プログラム」画面の適当な黒い背景部分を右クリックして「View page source」を選択してください。
すると下記画像の様に、このWebサイトを構成するHTMLのソースコードが見えるはずです。

page source

ちなみにGoogleAmazonなどの大きなWebサイトであっても、同様の手法でHTMLのソースコードを確認できます。(可読性は低いことが多いです。)

上記の画像をよく見てみると、先ほど入力したHTMLのコードが注入されていることが分かります。
ちなみに<h1>は見出しを作成する際に使用するHTMLタグで、大きい文字を出力したい時に使用します。
これでHTMLのコードを注入できることが分かりました。

それではXSSの神髄に迫りましょう。
HTMLタグの中に<script>というものがあります。これはスクリプトタグと呼ばれ、JavaScriptというプログラミング言語スクリプトタグ内に記述できます。
JavaScriptはブラウザ上で実行されるため、任意のコードが実行できてしまうとクライアントサイドの脆弱性となってしまうのです。

例えば下記の様なコードを入力してみましょう。

<script>alert(1)</script>

すると、アラートが表示されるはずです。

alert

これで任意のJavaScriptを実行できることが分かりました。

ただアラートを表示させるだけでは、脆弱性とはならないと思われる方もいるでしょう。
しかしXSSが可能であれば下記の様なことが可能となります。

  • セッションハイジャック(アカウントの乗っ取り)
  • Webページの改ざん
  • 悪質なWebサイトへの強制移動
  • フォームへの入力内容の窃取

他にも様々な被害が考えられますが、今回は「悪質なWebサイトへの強制移動」を試してみましょう。
では下記のコードを入力してみてください。

<script>location="https://www.google.com"</script>

するとGoogleへ移動したと思います。(今回はGoogleを悪質なWebサイトであると想定しました。)

Google

しかし疑問に思う方もいるでしょう。
今までは自分で入力したコードが自分のブラウザ上で実行されているだけで、どのように他ユーザーへの攻撃が成立するのでしょうか?

「2乗計算プログラム」に戻って、もう一度アラートのスクリプトを入力してください。

<script>alert(1)</script>

アドレスバーを見てみると、下記の様にGETリクエストのパラメータとして先ほどのスクリプトが見えると思います。(一部URLエンコードされているので分かりづらいかもしれません。)

http://10.0.2.23:3000/xss-get-1?number=%3Cscript%3Ealert%281%29%3C%2Fscript%3E

URL上に攻撃のスクリプトが混入できるということは、このURLを他人にクリックさせることができるということで、それは先ほどのJavaScriptを他ユーザーのブラウザ上で実行できることに繋がります。

今回はローカル環境で行っているため、みなさんの仮想環境でしか成り立ちませんが、例えば皆さんが使用しているショッピングサイトに反射型XSSがあればどうでしょうか?
反射型XSSを悪用した攻撃者が、クーポンを獲得できるURLを紹介しますというメールを送れば、一定数押してしまう人もいるでしょう。
XSSが普通のフィッシングメールに書かれている怪しいURLと比較して厄介なのは、ドメインが怪しく見えないということです。

怪しいフィッシングメールのURL例(ドメインは適当です)
https[:]//jfalksureoiewujfdalka-elkajjfadk.com/shop?product=%3Cscript%3Ealert%281%29%3C%2Fscript%3E

XSSを利用したURL例(ドメインは適当です)
https[:]//yourshopping-site.com/shop?product=%3Cscript%3Ealert%281%29%3C%2Fscript%3E


これがXSSの概要です。
今回は反射型の一番基本的なXSSを攻撃してみました。
冒頭でお伝えしたように、XSSには蓄積型やDOM型など様々であり、興味のある方はぜひご自身で調べてみてください。

XSS(クロスサイトスクリプティング) - Level2

ではトップページに戻ってLevel2に挑戦しましょう。
こちらも先ほどと同じ反射型のXSSになります。プログラムも先ほどと全く同じ「2乗計算プログラム」です。

Level2は、XSSへの対策を講じたプログラムです。
しかし対策が不十分なことから、対策を回避することが可能です。
もし自分で挑戦したい方がいればここで記事を読むのを止めて、ぜひ挑戦してみてください。


では解説していきます。
前回同様のアラートを出すペイロードを入力してみましょう。

<script>alert(1)</script>

するとどうでしょうか、JavaScriptが実行されていないことが分かります。

Level2

入力したペイロードの一部が、入力した数字の欄に残っています。
これはどういうことでしょうか?
詳細をつかむために、ページのソースを見てみましょう。

page source

すると開始スクリプトタグの<と>がなくなっていることに気が付きます。
サーバーサイドのソースコードがない状態であれば、ここから色々なペイロードを送信してみて挙動を把握していきますが、今回はサーバーサイドのソースコードを見てみましょう。

app.get('/xss-get-2', (req, res) => {
  var number = req.query.number;
  number = number.replace("<", "").replace(">", "");
  var square = number * number;
  res.render("xss-level2.ejs", { number: number , square: square });
});


プログラムを書いたことのない人にとっては見慣れないコードだと思いますが、注目してほしい所は3行目です。

number = number.replace("<", "").replace(">", "");

何をしているかというと、GETリクエストで送られたnumberパラメータの値の中に<と>があれば消してしまおうというものです。replaceメソッドを用いてそれを実現しています。

しかし思い出してみてください。
先ほどのアラートを発生させるスクリプトでは、終了タグ(</script>)はそのまま残っていました。
JavaScriptのreplaceメソッドを調べてみましょう。
www.javadrive.jp
記事を読んでみると、上記ソースコードのreplaceメソッドの使い方では、一度目のマッチでのみ置換が適応されるとのことです。
ということは下記の様なペイロードが対策を回避するために考えられるでしょう。

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

上記ペイロードでは先頭に中身のない空のタグを設置することで、空のタグ部分をreplaceメソッドで置換させ、残りのスクリプトを通常通り発火させることができます。
入力してみるとアラートを確認できます。

alert

このように脆弱性に対して対策が取られていたとしても、対策が不十分であれば回避することが可能であるということです。

対策

XSSへの対策は大きく分けて2つの方向性があります。
1つ目はインプットに対するバリデーションです。
Level2では、インプットに対してバリデーションがされているがその対策が不完全である例を示しました。
Level2ではタグを一度だけ置換していたことが問題なので、全てのタグを置換するようにすればリスクを低減することが可能です。
また、長く危険なスクリプトを挿入されることを防ぐために、サーバーにて文字数制限を設定することも効果的です。

2つ目がアウトプットに対するサニタイジングです。(こちらの方が導入が簡単で効果が大きいです。)
今回のアプリケーションは「Express」というフレームワークを用いて開発しています。
Expressのテンプレートエンジンである「ejs」では、簡単にXSSの対策をすることが可能です。

脆弱性のあるコード
<%- number %>
XSSの対策がされたコード
<%= number %>

numberは入力した数字を表しています。
このように「-」を「=」に変換するだけで簡単にXSSの対策をすることが可能です。
「=」ではエスケープ処理を行います。エスケープ処理とは、特殊記号をHTMLエンティティに変換することです。
昨今のWebアプリ開発では何かしらのフレームワークを使用することがほどんどです。
フレームワークでは、XSSへの対策が簡単に(もしくはデフォルトで)できるようになっていますので、開発する際は頭に入れておいてください。
基本的にインプットをバリデーションするよりも、アウトプットをサニタイジングするほうが難易度が低く、効果も絶大です。

お疲れ様でした。
次はSQLインジェクションです。

learn-ethicalhacking.hatenablog.com