はじめに
JSON や XML の入力だから安全?
いえ、残念ながら 構造化データでも中身の値は普通に注入されます。
REST API、GraphQL、モバイルアプリの普及によって、アプリは JSON/XML を大量にパースします。その入力値を SQL に直接渡してしまうと、古典的な SQL Injection と同じように攻撃が成立します。
本記事では XML / JSON Injection の仕組み、危険性、攻撃例、対策 を分かりやすく解説します。
1. XML / JSON Injection とは?
アプリケーションが受け取った JSON または XML をパースし、
そのまま SQL クエリに埋め込むことが原因で発生する注入攻撃 です。
構造化されていても、中身はただの “文字列”。
SQL の文脈にその文字列が入り込めば注入が成立します。
2. 典型的な JSON Injection の例
ユーザーが以下の JSON を送信:
{
"username": "admin' OR '1'='1--",
"password": "password"
}
アプリがパースした結果:
username = "admin' OR '1'='1--"
password = "password"
そして、もしアプリがこう SQL を生成していたら——
SELECT * FROM users
WHERE username = 'admin' OR '1'='1'--'
AND password = 'password';
結果:
-
OR '1'='1'が常に true - コメント
--で後続のパスワード条件が無効化 - 認証バイパスが成立
= SQL Injection 完全成功
3. XML Injection も本質は同じ
例えば以下の XML:
<login>
<username>admin' OR '1'='1--</username>
<password>password</password>
</login>
これをパースして SQL に投入すれば、JSON Injection と同じく攻撃成立。
さらに XML には XXE (XML External Entity) という “外部ファイル読み込み+内部情報漏洩” コンボ脆弱性も存在し、
XML Injection(値の注入)
+
XXE(ファイル読込/SSRF)
という “二刀流攻撃” の温床にもなります。
4. なぜ起きる?原因まとめ
| 原因 | 詳細 |
|---|---|
| ① 文字列連結で SQL を組み立てている |
"SELECT ... WHERE username='" + username + "'" のような組み方 |
| ② JSON / XML の入力値を信頼してしまう | “構造化されているから安全” は幻想 |
| ③ バリデーションが甘い | 長さチェック・空文字チェックだけなど |
| ④ Prepared Statement を使用していない | パラメータ化されていない SQL は攻撃者の遊び場 |
構造化データは “整理整頓されている” だけで、安全とは限りません。
5. 攻撃パターン例
パターン1:普通の JSON Injection
{ "username": "admin' OR '1'='1--" }
パターン2:XMLタグ内に SQL 断片を埋め込む
<id>1 OR 1=1</id>
パターン3:JSON 配列を悪用
{
"roles": ["admin' OR '1'='1--"]
}
パターン4:GraphQL 経由での注入
GraphQL → JSON → 文字列 → SQL
構造が複雑な分、コードの一部が脆弱になりがち。
6. 防御方法(これ守れば 95% 防げる)
1. Prepared Statement / Parameterized Query を必ず使う
SQL の文字列連結は禁止。
Java/Kotlin:
val stmt = conn.prepareStatement(
"SELECT * FROM users WHERE username = ? AND password = ?"
)
stmt.setString(1, username)
stmt.setString(2, password)
Python:
cursor.execute(
"SELECT * FROM users WHERE username=%s AND password=%s",
(username, password)
)
Node.js:
db.query("SELECT * FROM users WHERE username=? AND password=?", [u, p])
2. JSON / XML の値は「信用しない」
- 形式は正しい
- 型も正しい
- でも中身に攻撃 payload がある
→ よくある。
必ずエスケープ/サニタイズを行うこと。
3. XML の場合は XXE を無効化する(必須)
Java の場合:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
XXE を無効化しないと、
XML Injection + XXE でファイル漏洩 → SQL Injection
のコンボが成立する。
4. ORM / Query Builder を使う
ORM を正しく使えば SQL Injection の発生確率は激減。
ただし、生 SQL を書く部分があればそこは脆弱になるので注意。
まとめ
- JSON も XML も “構造化されているだけの文字列”
- 中身を SQL にそのまま渡すと Injection が成立する
- Prepared Statement を使えばほぼ防げる
- XML の場合は XXE もセットで対策が必要
「うちは REST API だから大丈夫」
「JSON しか使わないので安全」
→ こういう油断こそ攻撃者の大好物。