☠️

3種類のXSSについてまとめる

2022/12/16に公開

以前XSSについて勉強した時のメモが残っていたので、記事としてまとめて整理します。
私はセキュリティの専門家ではないため、間違っている点などございましたらご指摘いただけると幸いです。

XSS

XSSとは入力フィールドにJavascriptを入力して攻撃する手法のこと。
私が調べたところによると、初めてXSSについて言及されたのがCERT Advisory CA-2000-02で最も古かったです。
また、ここでは "cross-site" scripting との記述があり、一番初めの頃は一部でCSSという略称が使われていたように見えます。ただ、CSS(Cascading Stye Sheet)と見分けがつかないのでXSSとなったようです。

今ではとても一般的な攻撃手法で、バグバウンティでもこのXSSの報告が一番多い気がしますが、簡単なXSSはある程度できないようになっています。
例えば、Html5では、innerHTMLを使ってdomに入れたscriptタグは実行されないと規定されています。
https://www.w3.org/TR/2014/REC-html5-20141028/scripting-1.html#the-script-element

When inserted using the document.write() method, script elements execute (typically synchronously), but when inserted using innerHTML and outerHTML attributes, they do not execute at all.

XSSの種類

  • Stored(Persistent) XSS
  • Reflected(Non-Persistent) XSS
  • DOM-based(Non-Persistent) XSS

Persistent XSS

永続的(Persistent)に影響のあるXSS

Stored XSS

注入されたXSSペイロードがバックエンドのDBに保存され、ページを訪問した際に取得する場合、XSSは永続的(Persistent)となり、ページを訪問したすべてのユーザーに影響を与える可能性がある。

これを利用することでWebページの改竄などができてしまいます。

Tips:最近の多くのウェブアプリケーションは、クロスドメイン IFrame を利用してユーザ入力を処理するため、たとえウェブフォームが XSS に対して脆弱であっても、メインのウェブアプリケーションの脆弱性とはなりません。

Non-Persistent XSS

永続化することはないため、攻撃ターゲットとなるユーザにのみ影響する。

Reflected XSS

バックエンドサーバで処理されるXSS
Reflected XSS脆弱性は、入力がバックエンドサーバーに到達し、フィルタリングやサニタイズ処理が行われないままこちらに返された場合に発生します。

私はこれを学んだばかりの頃、XSSの脆弱性が非永続的であるならば、どのようにして攻撃するのだろうと思いましたが、XSSペイロードを含むURLを踏ませることによって、攻撃するようです。

http://157.245.33.77:32721/index.php?task=<script>alert(document.domain);</script>

↑の例では、alert()を実行するだけですが、alert()の代わりにより攻撃的なコードを仕込むことによって相手の情報を窃取することなどができてしまいます。

DOM XSS

バックエンドに到達せず、クライアント側で完全に処理されるXSSです。
DOM XSSは、JavaScriptがDocument Object Model(DOM)を通じてページのソースを変更するために使用される場合に発生します。
何か入力をした際に、ネットワークの通信が発生せずに画面が更新された場合はDOM操作が行われています。

DOM XSSをより理解するには、SourceとSinkというものを知っておく必要があります。

Source

ユーザーの入力を受け取るJavaScriptオブジェクトこのことで、URLパラメータや入力フィールドなどを指します。攻撃者はここを入り口にXSSペイロードを送ります。

Sink

ユーザーからの入力をページ上のDOM Objectに書き出す機能です。もしSinkとなる関数がユーザー入力を適切にサニタイズしていなければ、XSS攻撃を受ける可能性があります。
Sinkとなる関数としては次のようなものがあります。

  • document.write()
  • DOM.innerHTML
  • DOM.outerHTML
    また、jQueryでDOMへの書き込みが行われる関数としては次のようなものがあります。
  • add()
  • after()
  • append()

冒頭でも述べた通り、innerHTML関数は<script> タグを許可していなですが、<script>を使わないXSSペイロードはたくさんあり、もっと複雑なものまでいくらでもあるので、サニタイズを行うことが非常に重要です。
<script>を使わないXSSペイロードの例

<img src="" onerror=alert(window.origin)>

Discussion