2. MongoDB安全架构与威胁模型
MongoDB 的安全能力不是单一开关,而是一组按“先证明身份、再决定能做什么、再保护数据本身、最后留下可追溯证据”顺序协同工作的机制。理解这条链路,才能判断一次配置到底补上了哪一层,以及攻击者可能从哪一层绕过。
四层安全机制的分工
认证(Authentication)解决“你是谁”。MongoDB 支持 SCRAM-SHA-256(默认,用户名口令挑战应答)、x.509 证书、LDAP 代理认证和 Kerberos。副本集与分片集群必须启用内部认证(keyfile 或 x.509),否则节点间通信可被伪造。
授权(Authorization)解决“你能做什么”。基于角色的访问控制(RBAC)把权限绑定到角色,再把角色授予用户。权限由“资源 + 动作”组成,例如 { resource: { db: "shop", collection: "orders" }, actions: ["find","insert"] }。内置角色如 read、readWrite、dbAdmin、clusterMonitor、root 覆盖常见场景,最小权限原则要求优先使用自定义角色而非直接给 root。
加密(Encryption)分三个层面:传输加密(TLS/SSL,保护客户端与节点、节点与节点之间的链路)、静态加密(WiredTiger 加密存储引擎,保护磁盘文件与备份)、字段级加密(CSFLE / Queryable Encryption,保护敏感字段,使数据库管理员也看不到明文)。三者保护的对象不同,不能互相替代。
审计(Audit)解决“发生过什么”。MongoDB Enterprise 的审计功能可把认证、授权失败、DDL、CRUD 等事件写入 JSON 文件或 syslog,是合规取证与异常检测的基础。社区版可用 db.currentOp()、慢查询日志、profiler 与外部日志采集部分替代。
常见攻击面与真实威胁场景
MongoDB 历史上最典型的事故是“未启用认证 + 监听公网”。默认配置下若 bindIp 为 0.0.0.0 且未开启 security.authorization,任何能连到 27017 端口的人都可以直接读写全部数据库。攻击者常用脚本批量扫描 27017 端口,连接后执行 db.getCollectionNames() 枚举集合,再 dropDatabase() 并留下勒索信息。
第二类攻击面是注入。MongoDB 查询本身是文档,但应用若把用户输入直接拼进查询对象,攻击者可传入 {"$ne": null} 或 {"$gt": ""} 绕过条件判断。例如登录查询 db.users.find({user: username, pwd: password}),若 password 被替换为 {"$ne": 1},则条件恒真。防御手段是类型校验、使用 express-mongo-sanitize 类中间件剥离 $ 与 . 开头的键,以及禁用服务端 JavaScript(--noscripting)。
第三类是权限提升与横向移动。若应用账号拥有 dbAdmin 或 userAdminAnyDatabase,一旦被攻破,攻击者可创建新管理员账号、修改其他用户口令,甚至通过 db.runCommand({createUser:...}) 持久化后门。因此应用账号应严格限制在业务库的读写权限,管理操作走独立账号并配合 IP 白名单。
威胁建模方法:从数据流图到 STRIDE
威胁建模的目标是在编码前识别“哪里可能被攻破”。推荐流程:先画数据流图(DFD),标出外部实体、进程、数据存储与数据流;再划出信任边界(如公网→负载均衡、应用→数据库、数据库→备份存储);然后对每条跨越信任边界的数据流套用 STRIDE 六类威胁:仿冒(Spoofing)、篡改(Tampering)、抵赖(Repudiation)、信息泄露(Information Disclosure)、拒绝服务(Denial of Service)、权限提升(Elevation of Privilege)。
以“应用服务器 → MongoDB 副本集”这条流为例:仿冒对应未启用认证或弱口令;篡改对应未启用 TLS 导致中间人改写;信息泄露对应未启用字段级加密导致备份泄露;抵赖对应审计未开启;拒绝服务对应未限制连接数与查询复杂度;权限提升对应应用账号拥有 root。每条威胁再给出缓解措施与验证方式,形成可跟踪的清单。
最小可用的安全配置示例
下面是一份启用认证、TLS 与审计的 mongod.conf 片段,参数为教学示例,实际部署需替换为真实证书路径与密钥文件:
net:
port: 27017
bindIp: 10.0.1.21,127.0.0.1
tls:
mode: requireTLS
certificateKeyFile: /etc/ssl/mongodb.pem
CAFile: /etc/ssl/ca.pem
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
javascriptEnabled: false
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/audit.json
filter: '{ atype: { $in: ["authenticate","authCheck","createUser","dropDatabase"] } }'
setParameter:
authenticationMechanisms: SCRAM-SHA-256
验证时先确认未认证连接被拒绝:mongosh --host 10.0.1.21 --port 27017 应报认证错误;再用只读账号执行 db.orders.insertOne({}),应返回 Unauthorized;最后检查 audit.json 中是否出现对应的 authCheck 失败记录。三步都通过,说明认证、授权、审计三层已生效。
authorization 前必须先创建管理员用户,否则将无法执行任何需要授权的操作。建议在本地回环地址上先建好 userAdminAnyDatabase 账号,再开启授权并重启。加密的落地要点
TLS 要同时覆盖客户端连接与副本集内部通信,否则节点间复制仍是明文。静态加密需在启动时通过 --encryptionKeyFile 或 KMIP 提供主密钥,密钥一旦丢失数据不可恢复,因此密钥必须独立于数据库备份存放。字段级加密适合身份证号、手机号、支付信息等字段,客户端加密后再写入,服务端只存密文;其代价是无法对加密字段做范围查询(Queryable Encryption 可部分支持等值查询),需要在安全与查询能力之间权衡。
把四层机制串起来看:认证挡住匿名访问,授权限制已认证用户的动作范围,加密保护数据在传输、磁盘与字段三个位置的机密性,审计为前两者提供可验证的记录。威胁建模则是在部署前主动找出这四层各自的薄弱点,并用可执行的配置与验证步骤逐一封堵。