MongoDB默认配置下的未授权访问问题,至今仍是互联网上数据库被勒索的头号诱因之一。攻击者通过扫描公网27017端口,一旦发现未启用认证的实例,几秒内就能完成数据窃取或加密勒索。真正有效的防入侵,不是装个防火墙就完事,而是从部署架构、认证体系、权限模型到审计告警逐层设防。下面直接拆解可落地的实操技巧。

关闭公网暴露,用绑定地址限制监听范围

很多团队图省事,把MongoDB直接绑在0.0.0.0上,等于把数据库大门开到公网。第一件事就是修改mongod.conf中的bindIp,只允许内网网卡或特定管理网段访问。生产环境建议写成内网IP,例如:

net:
  port: 27017
  bindIp: 10.0.0.5,127.0.0.1

如果业务确实需要跨机房访问,不要直接暴露数据库端口,而是通过专线、VPC对等连接或跳板机中转。云服务器上尤其要注意安全组规则,只放行业务服务器的内网IP访问27017端口,拒绝0.0.0.0/0入站。公网扫描器之所以能批量得手,就是因为太多实例同时满足“绑定全网卡+安全组全放行”这两个条件。

强制启用认证,并关闭本地回环特权

MongoDB默认不开启认证,这是历史遗留设计。部署后第一件事是创建管理员账号,然后重启实例并加上--auth参数。创建管理员时不要用常见用户名,避免被字典爆破。示例:

use admin
db.createUser({
  user: "dbadmin_x7k2",
  pwd: "强密码至少16位含大小写数字符号",
  roles: [ { role: "root", db: "admin" } ]
})

重启后启用认证:

security:
  authorization: enabled

注意,如果MongoDB同时开启了localhost exception,未认证用户仍可从本机绕过认证。这个机制在3.6之后默认关闭,但老版本升级上来的实例要检查。确认方式是在未认证状态下从127.0.0.1执行db.adminCommand({usersInfo:1}),如果返回用户信息,说明本地回环特权还在,需要重启并确保authorization参数生效。

用最小权限原则替代root角色

很多开发者图方便,所有应用都拿root账号连接数据库。一旦应用被SQL注入或代码泄露,攻击者直接获得数据库最高权限。正确做法是按业务库分配角色,应用账号只拥有对应库的readWrite权限,报表系统只给read权限。例如:

use appdb
db.createUser({
  user: "app_user",
  pwd: "应用独立强密码",
  roles: [ { role: "readWrite", db: "appdb" } ]
})

对于需要跨库聚合查询的场景,可以自定义角色,精确到集合级别。比如只允许某个账号读取日志库中的特定集合:

db.createRole({
  role: "log_reader",
  privileges: [
    { resource: { db: "logs", collection: "access_log" }, actions: ["find"] }
  ],
  roles: []
})

权限越细,单点被突破后的损失面就越小。定期审查账号权限,下线不再使用的账号,是防入侵中成本最低但最容易被忽略的一环。

启用TLS加密传输,防止内网嗅探

即使数据库只在内网,明文传输依然存在风险。内网中的恶意进程、被攻陷的同网段主机,都可能抓包获取查询语句和返回数据。MongoDB支持TLS加密客户端与节点间通信,配置如下:

net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/mongodb/ssl/server.pem
    CAFile: /etc/mongodb/ssl/ca.pem

生成证书时,服务器证书的CN或SAN必须包含客户端连接时使用的域名或IP,否则客户端会校验失败。副本集内部通信建议使用独立的内部证书,并开启internalAuth,防止攻击者伪装成副本节点加入集群窃取数据。

开启审计日志,记录敏感操作

没有审计的数据库,被入侵后连攻击者做了什么都不知道。MongoDB企业版自带审计功能,社区版可以通过mongod参数--auditDestination输出到文件或syslog。重点审计以下操作:创建删除用户、修改角色、删除数据库、删除集合、查看系统集合。配置示例:

auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/audit.json
  filter: '{ atype: { $in: ["createUser", "dropUser", "dropDatabase", "dropCollection", "updateUser"] } }'

审计日志要写到独立磁盘或实时同步到远端日志系统,否则攻击者拿到数据库权限后顺手把审计日志也清掉,防线就白建了。定期分析审计日志中的异常模式,比如非工作时间的大量删除操作、陌生IP的认证失败记录,都能提前发现入侵迹象。

利用网络层访问控制与速率限制

除了MongoDB自身的认证,还应在网络层做第二道防线。iptables或云安全组可以限制源IP,但更精细的控制需要借助MongoDB的authenticationRestrictions参数,它允许在账号级别绑定客户端IP或CIDR。例如只允许应用服务器网段登录:

db.createUser({
  user: "app_user",
  pwd: "强密码",
  roles: [ { role: "readWrite", db: "appdb" } ],
  authenticationRestrictions: [
    { clientSource: ["10.0.1.0/24"], serverAddress: ["10.0.0.5"] }
  ]
})

这样即使密码泄露,攻击者从其他网段也无法认证。另外,MongoDB没有内置登录失败锁定机制,但可以通过fail2ban监控mongod日志中的认证失败记录,自动封禁暴力破解源IP。在公网边缘设备上配置连接速率限制,能有效缓解扫描器和自动化攻击工具。

及时升级版本并关注安全公告

MongoDB官方会定期发布安全补丁,很多入侵事件利用的都是已公开的旧漏洞。例如CVE-2019-2386允许绕过部分认证检查,CVE-2020-7924影响特定版本下的权限提升。运维团队应建立版本升级机制,至少保持在最近两个大版本的最新小版本。升级前在测试环境验证兼容性,尤其是驱动版本与数据库版本的匹配。对于无法立即升级的老版本,至少要通过配置规避已知漏洞的触发条件,比如关闭不用的服务端JavaScript执行。

备份策略是最后一道防线

防入侵做得再好,也无法保证100%不被突破。勒索攻击的最终目的是让数据不可用,而有效的备份可以让攻击者失去筹码。MongoDB备份要满足三点:定期自动执行、备份文件与生产环境隔离、定期做恢复演练。mongodump适合小规模数据,大规模数据建议用文件系统快照或MongoDB Ops Manager的物理备份。备份文件不要放在数据库同一台机器上,最好同步到对象存储或离线介质。恢复演练至少每季度做一次,确认备份可用、恢复流程清晰、RPO和RTO满足业务要求。

监控关键指标,建立异常告警

入侵行为往往伴随资源异常或操作模式突变。监控MongoDB的以下指标:连接数突增、慢查询数量异常、磁盘IO持续高位、网络流量突然增大、认证失败次数激增。这些指标可以通过mongostat、Prometheus exporter或云监控服务采集。当认证失败次数在短时间内超过阈值,或者出现来自陌生IP的连接请求,应立即触发告警并自动阻断。监控本身不直接阻止入侵,但它能大幅缩短发现时间,把损失控制在最小范围。

MongoDB防入侵不是一次性配置,而是持续的过程。从关闭公网访问、强制认证、最小权限、TLS加密,到审计、网络限制、版本更新、备份和监控,每一层都在增加攻击成本。实际落地时,优先把前四步做好,就能挡住绝大多数自动化扫描和批量勒索。剩下的工作,是让安全配置跟上业务变化,定期复查和加固。