😃

PortSwigger Web Security Academy Writeup【XSS編①DOM-based XSS】

2023/08/16に公開

1. ご挨拶

はじめまして、タタラと申します。
今回はPortSwigger社が運営するlabs(脆弱性のPoCを行える環境)のうち、DOM-based XSSを扱ったラボを攻略したので、思考の過程を整理する目的で書いていきます。
実際のペイロードも記載しておりますので、ネタバレ注意でお願いします。
PortSwiggerのサイトはこちら(https://portswigger.net/)

2. 目次

  1. ご挨拶
  2. 目次
  3. DOM-based XSSとは
  4. ラボを攻略
    4-1. 攻撃対象となる機能
    4-2. 回答
  5. 関連するWeb API
  6. その他気になったこと、試したこと
  7. 参考文献

3. DOM-based XSSとは

DOM-based XSSとは、JavaScriptでDOM(Document Object Model)を操作する場合に発生しうる脆弱性です。Reflected XSSやStored XSSはサーバ側のプログラムの不備によって発生しますが、DOM-based XSSはフロントエンド側のプログラムの不備によって発生します。

4. ラボを攻略

4-1. 攻撃対象となる機能

今回攻略したラボはブログサイトを模した環境です。写真中のワード検索機能に脆弱性が存在します。

正常な値を入れて検索ボタンを押すと、上記の検索結果ページに遷移します。URLのクエリストリングに検索ワードが入れられています。

4-2. 回答

とりあえずXSS脆弱性の有無を検証する上で基本的なペイロード(alert関数)を入力してみましたが上手くいきませんでした。

そこで、検索ボタンを押下してから結果ページが表示されるまでに処理の流れを確認しました。

1.検索ワードを入力して検索ボタンを押下すると、'search'パラメータに検索ワードが入ったGetリクエストが発行されます。

2.検索結果ページをディベロッパツールで確認すると、パラメータ'search'に入った値を扱うインラインスクリプトを発見しました。
 document.write()関数を用いてページ内に<img>タグを埋め込む処理と思われます。

入力値をGIF画像のソースパスの要素として用いているため、alert関数の前後にソースパスを指定するための'(セミコロン)や<img>タグを閉じる'>'を入れれば良さそうです。
よって

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

をペイロードとして入力しました。すると...


alert関数が動作しました!このことから、このブログサイトでは攻撃者が任意のJavaScriptを実行可能であるとわかります。

このラボはこれにてクリアとなります。
Web Security Academyのページでは他の回答も紹介されているので、興味のある方はご覧ください。
(https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-document-write-sink)

5. 関連するWeb API

今回攻略したラボでは、ユーザの入力値をGIF画像のソースパスの一部として利用し、document.write関数でHTML内に<img>タグを埋め込み処理に脆弱性が存在しました。
このスクリプトで利用されているAPIについて、簡単にまとめておきます。

・URLSearchParams
 クエリパラメータを操作する上で有用なメソッドを提供するAPI。
今回のスクリプトではget()メソッドでパラメータ'search'に対応する値を取得していました。

・window.location.search
 windowインターフェースはDOMオブジェクトを収めるウィンドウを表します。
window.locationプロパティはスクリプトが実行されているファイルのlocationオブジェクトを返します。
window.location.searchプロパティはスクリプトが実行されているファイルのURLのクエリストリングを返します(?記号を含む)。
今回のスクリプトではURLから?search=ユーザの入力値を抜き出していました。

・document.write()
  document.open()メソッドで開かれた文書にテキストの文字列を書き込むメソッド。
 今回のスクリプトでは、ユーザの入力値を要素として作成したソースパスを含む<img>タグをファイル内に書き込む処理を行っていました。

6. その他気になったこと、試したこと

今回のラボで使われていたスクリプトを元に、ユーザの入力値を受け付けるページと入力値を表示するページを作成したところ、DOM-based XSSを再現できました。

sendForm.html
<!DOCTYPE html>
<html>
	<head>
		<title>Form Page</title>
		<meta charset="utf-8">
	</head>
	<body>
		<h1>入力ページ</h1>
		<p>ペイロードを入力</p>
		<form action="./receive.html" id="form" method="Get" />
			<input type="text" name="payload" required/> 
			<input type="submit" />
		</form>
	</body>
</html>
receive.html
<!DOCTYPE html>
<html>
	<head>
		<title>receive Page</title>
		<meta charset="utf-8">
		<script>
			document.open()
			let query = new URLSearchParams(window.location.search).get('payload')
			document.write(query)
			document.close()
		</script>
	</head>
	<body>
		<h1>入力データ受け取りページ</h1>
	</body>
</html>

補足:
location.searchのようにDOM-based XSS脆弱性が生じる原因になりうる箇所を「ソース」、document.write()のようにユーザが入力したJavaScriptを実行してしまう箇所を「シンク」と呼びます。

今回は以上となります。ありがとうございました。

7.参考文献

Discussion