正文

数据库端口不是 API,不应该直接暴露给任何能连上公网的人。页面有登录、接口有鉴权、后台有权限,都不能替代数据库层的网络隔离。只要 Redis、ClickHouse、Elasticsearch、Kibana、Qdrant、Weaviate、Milvus 这类服务被放到公网,攻击者可能绕过应用层,直接读数据、删数据、改索引、枚举集合、下载向量 payload,甚至借助管理接口继续横向移动。

真实事故已经反复说明,问题经常不是复杂漏洞,而是“门开着”。

2025-01-29,Wired 报道 Wiz 研究人员发现 DeepSeek 一个 ClickHouse 数据库暴露在互联网上,里面包含系统日志、用户 prompt、API authentication tokens 等超过 100 万条记录。The Verge 也报道,这个数据库无需认证即可访问,并且可能允许完整数据库控制和权限提升。这个案例对 AI 应用尤其直接:prompt、日志、API key、路由路径、内部元数据都可能被写进分析库,分析库一旦公网裸露,应用层再多登录态也挡不住。

2018-06-27,Wired 报道营销公司 Exactis 暴露了约 3.4 亿条个人和企业记录。研究人员用 Shodan 搜索公开可访问的 Elasticsearch 实例时发现了这个数据库。它不一定是“黑客入侵”造成的传统漏洞,但对用户来说结果一样:大量个人画像、手机号、住址、邮箱和兴趣标签被放到了可被发现的服务器上。

Redis 官方安全文档也写得很明确:Redis 设计上通常应由可信环境里的可信客户端访问,不建议把 Redis 实例直接暴露到互联网;Redis 端口应该只允许可信客户端访问。Qdrant 官方文档同样提醒,自部署 Qdrant 默认没有认证,并且监听所有网络接口,生产前必须配置认证、审计日志、网络绑定和 TLS。

上线前先查这些入口:

Redis6379
ClickHouse8123 / 9000
Elasticsearch9200 / 9300
Kibana5601
Qdrant6333 / 6334 / 6335
Milvus19530
Weaviate8080

先列出哪些数据库能被访问

不要只看应用代码。数据库可能从 Docker、Kubernetes、云安全组、临时测试机、旧域名、VPN 旁路、监控面板或备份服务暴露出去。

先扫仓库里的端口和服务名:

再重点查部署文件:

把每个数据库写成一张表:

通过标准:生产数据库没有直接公网入口;确实需要跨网络访问时,走私网连接、VPN、堡垒机、PrivateLink 或受控网关。

服务Redis / ClickHouse / Elasticsearch / Qdrant
环境dev / staging / production
监听地址127.0.0.1 / 私网 IP / 0.0.0.0
入口内网、VPN、堡垒机、公网 LB、Kubernetes Service
调用方应用服务、后台任务、BI、监控、AI Agent
凭据无、密码、ACL、API key、TLS client cert
数据类型缓存、日志、订单、prompt、向量 payload
PowerShell
rg -n "6379|8123|9000|9200|9300|5601|6333|6334|6335|19530|8080|redis|clickhouse|elasticsearch|kibana|qdrant|weaviate|milvus" .
PowerShell
rg -n "ports:|hostPort|NodePort|LoadBalancer|0\\.0\\.0\\.0|allow|cidr|securityGroup|ingress" docker-compose.yml docker-compose.yaml Dockerfile k8s deploy .github

不要把数据库端口当 API 发布

数据库端口暴露和 API 暴露不是一个级别的风险。API 至少还能在业务层做鉴权、限流、字段过滤、审计和错误处理;数据库端口一旦暴露,攻击者面对的是原始查询能力。

危险写法:

本机开发可以只绑定本地回环:

生产环境更稳的方式是不要发布端口,只让同一私有网络里的应用服务访问:

通过标准:生产 Docker Compose、Kubernetes、云主机和负载均衡器里,看不到数据库端口对 0.0.0.0/0 或公开 IP 开放。

YAML
services:
  redis:
    image: redis:latest
    ports:
      - "6379:6379"

  elasticsearch:
    image: elasticsearch:8.19.0
    ports:
      - "9200:9200"
YAML
services:
  redis:
    image: redis:latest
    ports:
      - "127.0.0.1:6379:6379"
YAML
services:
  redis:
    image: redis:latest
    expose:
      - "6379"

Redis 先查 bind、protected mode 和 ACL

Redis 官方文档强调,Redis 通常应该被可信环境里的可信客户端访问,不建议直接暴露到互联网。它还特别提醒,外部攻击者一个 FLUSHALL 就能删除整个数据集。

先查配置:

危险信号:

本地开发可以绑定回环:

生产至少要做到:

通过标准:从公网机器无法连通 Redis;从应用机器连接时需要认证;业务账号只能执行它需要的命令。

  • 只允许应用服务所在私网访问 Redis。
  • 使用 Redis 6+ ACL,按应用创建独立用户。
  • 禁止业务账号执行 FLUSHALLCONFIGKEYS、危险 Lua 脚本。
  • 开启 TLS 或放在受控私有网络里。
  • 不把 Redis 当长期事实数据库保存敏感数据。
bind 0.0.0.0所有网卡都能接收连接
protected-mode no关闭默认保护
没有 ACL / 密码能连上就能操作
业务账号可执行 FLUSHALLCONFIG应用被打穿后可扩大破坏
明文 Redis 密码进入日志或镜像凭据可被二次利用
PowerShell
rg -n "bind |protected-mode|requirepass|user |rename-command|aclfile" redis.conf docker-compose.yml .env .env.example
Text
bind 127.0.0.1
protected-mode yes

ClickHouse 先查 8123、9000 和 default 用户

ClickHouse 常用于日志、事件、埋点、BI 和 AI prompt 分析。它的数据看起来像“日志”,实际可能包含用户输入、API key、内部路径、手机号、订单号、设备标识和业务事件。

先查端口:

ClickHouse 文档里 listen_host 用来限制请求来源。如果配置成回答所有地址,数据库端口就可能被外部访问。

危险信号:

更稳的配置思路:

通过标准:ClickHouse 的 HTTP/TCP 端口只在私网可达;默认用户不能远程访问;BI、应用、分析任务使用不同账号和最小权限。

<listen_host>0.0.0.0</listen_host>对所有 IPv4 地址监听
<listen_host>::</listen_host>对所有 IPv6 地址监听
default 用户仍可远程登录默认账号风险过高
用户无密码或弱密码被扫到后可直接查询
查询日志长期保存 prompt / token数据库本身变成敏感日志仓库
BI 工具直连生产库用户权限和查询审计容易失控
PowerShell
rg -n "8123|9000|9004|9005|listen_host|clickhouse" .
Text
listen_host: 127.0.0.1 or private IP
users: no default remote login
roles: read-only role for BI
quotas: query complexity and rate limits
logs: no raw token, no full prompt, no payment payload

Elasticsearch 和 Kibana 要一起查

Elasticsearch 暴露通常不只暴露搜索。它可能包含业务索引、日志索引、错误堆栈、用户画像、订单、客服记录、地理位置、设备信息和内部事件。

先查端口和安全配置:

危险信号:

Elastic 官方文档把认证授权、TLS、API keys、IP filters、PrivateLink/VPC filtering 都放在安全配置里。生产环境不要把 Elasticsearch 当成“只读搜索服务”裸露给前端或公网。

通过标准:

  • Elasticsearch HTTP 端口不对公网开放。
  • Kibana 有 SSO/认证,不允许匿名访问内部 dashboard。
  • 应用账号只拥有指定索引的读写权限。
  • 日志索引有字段脱敏和保留期限。
  • 快照仓库不公开,恢复权限单独控制。
network.host: 0.0.0.0可能对外监听
没有认证和 TLS能连上就能查索引
Kibana 公网开放通过 UI 看数据和 saved objects
日志索引保存完整 headers/bodytoken、cookie、手机号、prompt 二次泄露
统一使用管理员账号应用、BI、运维无法隔离
PowerShell
rg -n "9200|9300|5601|elasticsearch|kibana|xpack.security|ELASTIC_PASSWORD|network.host" .

向量库先查 API key、payload 和 collection

向量库容易被低估,因为开发者以为里面只是 embedding。实际生产 RAG 系统里,向量库经常保存:

Qdrant 官方文档明确提醒,自部署 Qdrant 默认不安全:监听所有网络接口,没有认证,可能被互联网上任何能访问的人调用。生产前应配置 API key、审计日志、网络绑定和 TLS。

先查向量库端口:

危险信号:

向量库账号要按用途拆:

通过标准:公网不能直接列出 collection;检索接口会按用户/租户过滤;向量 payload 不保存不必要的原文敏感数据。

  • 原文片段。
  • 文档标题、URL、用户 ID、租户 ID。
  • 客服对话、合同条款、简历内容。
  • 权限标签、部门、项目名。
  • prompt cache、工具调用结果。
Qdrant自部署默认无认证,6333 / 6334 暴露后可枚举 collection
Weaviateschema、objects、modules 可能被匿名查询
Milvuscollection、partition、向量和 metadata 需要网络隔离
Chroma本地开发常见,不能直接当公网服务
检索服务只读、限定 collection
写入任务只能写指定 collection
管理任务需要人工触发,不能给前端
AI Agent优先只读、只给脱敏数据
PowerShell
rg -n "6333|6334|6335|19530|8080|qdrant|weaviate|milvus|chroma|vector|embedding|collection" .

云安全组不要放开 0.0.0.0/0

很多数据库暴露不是配置文件写错,而是云安全组、Kubernetes Service 或负载均衡器放开了入口。

上线前检查这些位置:

Terraform 里看到这类规则要退回:

更稳的做法是只允许应用服务安全组或私网 CIDR:

通过标准:数据库端口只对应用服务、运维入口、受控私网开放,不对全网开放。

AWS / Azure / GCP 安全组数据库端口是否允许 0.0.0.0/0::/0
Kubernetes Service是否把数据库设成 LoadBalancer / NodePort
Ingress / Gateway是否把 Kibana、管理面板、向量库 API 挂到公网域名
Docker Compose是否用了 "6379:6379" 这类公开端口映射
Terraform是否把数据库端口写进公共 ingress rule
监控系统Prometheus、Grafana、Kibana 是否匿名开放
hcl
cidr_blocks = ["0.0.0.0/0"]
from_port   = 9200
to_port     = 9200
hcl
source_security_group_id = aws_security_group.app.id
from_port                = 9200
to_port                  = 9200

应用账号只给最小权限

网络隔离不是唯一防线。应用一旦有 SSRF、命令执行、依赖投毒或 CI 泄密,数据库凭据也可能被读走。此时最小权限能限制损失。

账号拆分建议:

不要让应用默认拿管理员账号。不要把 BI、客服后台、AI Agent、定时任务和线上应用共用同一个数据库用户。

通过标准:单个应用凭据泄露时,攻击者不能读所有库、删所有索引、改所有 collection,也不能创建新管理员。

app_readwrite只访问当前应用需要的库、表、索引或 collection
app_readonly只读接口、报表、搜索
migration只在迁移窗口使用,平时禁用
backup只读备份所需范围
bi_readonly只读脱敏视图,不直连原始敏感表
admin人工使用,强 MFA,审计记录完整

备份、快照和管理面板同样要查

很多团队只锁主库,忘了副本和备份:

上线前查这些文件名:

备份要满足:

备份文件一旦公开,风险通常比主库更大,因为它绕过了在线权限系统。

  • Elasticsearch snapshot repository。
  • ClickHouse backup 文件和对象存储桶。
  • Redis RDB / AOF 文件。
  • Qdrant snapshot。
  • Kibana saved objects。
  • 数据库 Web 管理面板。
  • 临时导出的 CSV / parquet / dump。
存储位置私有 bucket / 私有对象存储
访问权限只有备份服务和少数运维可读
加密传输和静态存储都加密
保留期限到期自动删除
恢复演练能恢复,但不把生产数据恢复到公网测试环境
脱敏研发、AI、BI 用脱敏副本
PowerShell
rg -n "dump|backup|snapshot|\\.rdb|\\.aof|\\.sql|\\.parquet|\\.csv|saved_objects|exports" .

上线前跑一张数据库暴露检查表

发布前至少确认这些项:

再用只针对自己资产的连通性检查确认外部无法访问。不要扫描第三方 IP。

通过标准:从公网网络测试数据库端口应该失败;从应用所在私网测试应该成功,并且需要认证。

Text
- [ ] Redis, ClickHouse, Elasticsearch, Kibana and vector DB ports are not open to 0.0.0.0/0
- [ ] Docker Compose does not publish database ports in production
- [ ] Kubernetes database Services are not LoadBalancer or public NodePort
- [ ] Cloud security groups only allow app/private network sources
- [ ] Redis uses bind/protected mode/ACL and blocks dangerous commands for app users
- [ ] ClickHouse listen_host is private and default user is not remotely usable
- [ ] Elasticsearch security, TLS and index-level permissions are enabled
- [ ] Kibana requires authentication and is not anonymously reachable
- [ ] Vector DB uses API key/TLS and collection-level access where available
- [ ] App users are not database admins
- [ ] BI and AI Agent accounts use read-only or scoped credentials
- [ ] Logs, prompt, headers and payment payload are not stored as raw searchable fields
- [ ] Backups, snapshots and exports are private and encrypted
- [ ] Audit logs can show who queried, exported, deleted or changed data
- [ ] A credential rotation plan exists if exposure is found
PowerShell
Test-NetConnection your-owned-host.example.com -Port 6379
Test-NetConnection your-owned-host.example.com -Port 9200
Test-NetConnection your-owned-host.example.com -Port 6333

已经暴露怎么办

发现数据库曾经暴露后,不要只把安全组关掉。

按泄露处理:

数据库公网暴露的根因通常不是“某个数据库不安全”,而是上线时把开发便利当成生产入口。开发环境可以临时连,生产环境必须能回答三个问题:谁能连、连上后能做什么、做过什么能不能追到。答不清楚,就不要上线。

  • 立即移除公网入口:安全组、负载均衡器、端口映射、Kubernetes Service、Ingress。
  • 保留必要证据:暴露时间、端口、访问日志、云审计日志、数据库审计日志。
  • 轮换数据库账号、Redis ACL、Qdrant API key、Elasticsearch API key、应用 .env
  • 检查是否有异常查询、批量导出、索引删除、collection 修改、未知账号创建。
  • 如果暴露了 prompt、聊天记录、手机号、邮箱、订单、支付信息,按隐私和合规流程评估通知。
  • 清理公开备份、日志、镜像、CI artifacts 里复制出来的数据库连接串和 dump。
  • 给数据库加私网访问、最小权限、审计、告警和到期删除。

参考来源

Exposed DeepSeek Database Revealed Chat Prompts and Internal DataWiredDeepSeek database left user data, chat histories exposed for anyone to seeThe VergeMarketing Firm Exactis Leaked a Personal Info Database With 340 Million RecordsWiredRedis securityRedis DocsSecurityElastic DocsServer Settings: listen_hostClickHouse DocsAccess control and account managementClickHouse DocsSecurityQdrant Docs

相关文章

API 接口上线前要查什么:鉴权、越权、限流、幂等和错误返回工程实践 / 约 13 分钟日志不是越详细越好:开发者如何避免把 token、手机号、订单和 prompt 打进日志工程实践 / 约 12 分钟Docker 镜像里最容易泄露什么:.env、构建缓存、SSH key 和多阶段构建工程实践 / 约 12 分钟GitHub Actions 不是能跑就行:第三方 Action、secrets、权限和日志怎么查工程实践 / 约 13 分钟Vibe Coding 小应用上线前要查哪些安全坑智能编程 / 约 12 分钟npm 供应链攻击后,开发者要怎么检查依赖、lockfile 和 CI 密钥工程实践 / 约 13 分钟AI Agent 权限怎么设:哪些命令能自动跑,哪些必须人工确认智能编程 / 约 13 分钟MCP Server 安装前怎么检查 tool poisoning 风险智能编程 / 约 12 分钟

作者信息