①绑定IP和修改默认端口
27017
确保MongoDB使用非默认端口服务配置
描述
更改MongoDB使用的端口使攻击者更难找到数据库并将其作为目标。
标准端口用于自动攻击,并由攻击者用于验证服务器上正在运行的应用程序。
检查提示
--
加固建议
将MongoDB服务器的端口更改为27017以外的数字
②确保MongoDB仅侦听授权接口上的网络连接访问控制
描述
确保MongoDB在受信任的网络环境中运行涉及限制MongoDB实例侦听传入连接的网络接口。
MongoDB应删除任何不受信任的网络连接。 此配置阻止来自不受信任网络的连接,
只允许授权和受信任网络上的系统尝试连接到MongoDB。
如果未配置,则可能导致从不受信任的网络到MongoDB的未授权连接。
检查提示
--
加固建议
1、如果服务只允许本机访问,编辑MongoDB的配置文件<conf_path>/mongod.conf,在net区块下配置bindIp,
将此项的值设置为:127.0.0.1(仅允许本机访问),并重启MongoDB服务。
2、如业务需要设置为跨服务器访问,可通过安全组配置访问规则,防止服务暴露到互联网上,然后忽略此项
③确保在不需要时禁用服务器端脚本服务配置
描述
MongoDB支持为某些服务器端操作执行JavaScript代码:mapReduce,group和$ where。
如果不使用这些操作,则应禁用服务器端脚本。 如果不需要服务器端脚本并且未禁用,则会带来不必要的风险,即攻击者可能会利用不安全的编码。
不需要执行js脚本,使用--noscripting禁止脚本执行
检查提示
--
加固建议
编辑<conf_file>/mongod.conf文件中将security下的javascriptEnabled:设置为false`以禁用它。
④确保正确设置了数据库文件权限文件权限
描述
MongoDB数据库文件需要使用文件权限进行保护。这将限制未经授权的用户访问数据库。
检查提示
--
加固建议
将数据库文件的所有权设置为mongodb用户,并使用以下命令删除其他权限:
chmod 600 /var/lib/mongodb
sudo chown mongodb:mongodb /var/lib/mongodb
以上命令为默认数据库文件路径,请根据实际环境修改为正确数据库文件路径。
⑤确保正确设置了密钥文件权限文件权限
描述
密钥文件用于分片群集中的身份验证。 在密钥文件上实现适当的文件权限将防止对其进行未经授权的访问。
保护密钥文件可加强分片集群中的身份验证,并防止对MongoDB数据库的未授权访问。
检查提示
--
加固建议
将keyFile所有权设置为mongodb用户,并通过执行以下命令删除其他权限:
chmod 600 <keyfile_path>/keyfile
sudo chown mongodb:mongodb <keyfile_path>/keyfile
⑥确保将新条目附加到日志文件的末尾安全审计
描述
默认情况下,新的日志条目将在重新启动mongod或Mongols服务后覆盖旧条目。
启用systemLog.logAppend设置会导致新条目附加到日志文件的末尾,而不是在mongos或mongod实例重新启动时覆盖日志的现有内容。
允许旧条目被新条目覆盖而不是将新条目附加到日志末尾可能会破坏出于各种目的所需的旧日志数据。
检查提示
--
加固建议
编辑配置文件<conf_path>/mongod.conf将systemLog下的logAppend设置为true。
⑦确保日志记录捕获尽可能多的信息安全审计
描述
SystemLog.quiet选项停止记录信息,例如:
?连接事件
?身份验证事件
?复制同步活动
?运行一些可能有影响的命令的证据(例如:drop,dropIndexes,
验证)
应尽可能记录此信息。 此检查仅适用于Enterprise
版本。
使用SystemLog.quiet可以解决问题并进行调查
安全事件要困难得多。
检查提示
--
加固建议
编辑<conf_file>/mongod.conf文件中将SystemLog下的quiet设置为False以禁用它。
⑧确保使用非特权的专用服务帐户运行MongoDB访问控制
启用访问控制并强制执行身份认证,不同用户不同账户,应用隔离
不给多余权限,最小权限原则
描述
MongoDB服务不应使用特权帐户(如“root”)运行,因为这会不必要地将操作系统暴露在高风险之下。
使用非特权专用服务帐户限制数据库访问MongoDB不需要的操作系统的关键区域。 这还将减少通过操作系统上受损的特权帐户进行未经授权访问的可能性。
检查提示
--
加固建议
1.创建用于执行MongoDB数据库活动的专用用户。
2.将数据库数据文件,密钥文件和SSL私钥文件设置为只能读取 由mongod/mongos用户提供。
3.将日志文件设置为只能由mongod/mongos用户写入,并且只能由root读取。
4.切换至该专用用户,并重启MongoDB
⑨确保MongoDB使用了符合口令复杂度规则的口令访问控制
描述
MongoDB登录账户常见弱口令检测。
检查提示
存在弱密码(端口:数据库.用户名|密码):27017:未启用账号密码认证
加固建议
该帐号发现弱口令,为了保证系统不被黑客恶意猜解入侵,请修改为12位以上,数字/字母/特殊字符组合的强口令
修复操作步骤:
1.打开mongodb客户端;
2.执行命令:use admin;
3.登录管理员账户:db.auth("<username>","<password>");
4.执行命令:use <db_name>,db_name为待修改用户所属的数据库名;
5.执行命令:db.updateUser('<username>',{pwd:'<newpassword>'}),username为待修改的用户名,newpassword为新口令。
另外需要确保开启了身份认证功能,编辑MongoDB配置文件<conf_path>/mongod.conf中的 auth配置项为auth = true,
然后重启MongoDB服务 注:修改口令后需过一小段时间才能检测出是否为弱口令。
⑩确保为MongoDB数据库启用了身份验证身份鉴别
当authorization为disabled时,登录不需要验证账号密码。为enabled需要验证!
描述
此设置可确保所有客户端,用户和/或服务器都需要进行身份验证
在被授予访问MongoDB数据库之前。
无法对客户端,用户和/或服务器进行身份验证可以启用对服务器的未授权访问
MongoDB数据库可以防止跟踪操作返回其源。
检查提示
--
加固建议
编辑MongoDB配置文件,在security区块下配置 authorization: enabled
命令行启动加 --auth 参数
mongod -- port 27017 --dbpath ./db/ --fork --logpath mongod.log #启动无鉴权
mongod -- port 27017 --dbpath ./db/ --fork --logpath mongod.log --auth #启动鉴权
启用鉴权后,无密码可以登录,但只能执行创建用户操作
增删改查用户及权限
use admin
show users;//查看所有用户
db.getUsers();//查看所有用户
db.createUser({user:"root",pwd:"root",roles:[{role:"root",db:"admin"}]}) #创建超级用户
db.createUser({user:"reader",pwd:"reader",roles:[{role:"read",db:"test"}]})#创建test库只读用户
db.createUser({user:"writer",pwd:"writer",roles:[{role:"readWrite",db:"test"}]})#创建test库读写用户
mongo -u root -p root --authenticationDatabase test #指定登录的数据库
//创建用户及权限
> db.createUser(
{
user:"test",
pwd:"test",
roles:[{role:"root",db:"admin"}]
}
)
//创建用户成功提示
Successfully added user: {
"user" : "test",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
//创建用户分配数据库权限
> db.createUser(
{
user:"test",
pwd:"testpwd",
roles:[{role:"readWrite",db:"test"},{role:"read",db:"admin"}]
}
)
> db.updateUser("test",{pwd:"12345",roles:[{role:"root",db:"test"}]});//更新用户及权限
> //更新成功提示无
> db.changeUserPassword("test","testpwd");//更改用户密码
> //更新成功提示无
> db.dropUser('test');//删除用户
true //删除用户成功提示
#/www/server/mongodb/bin/mongo -host 127.0.0.1 -port 27017 -u root -p #回车输入密码,登录同时验证
#/www/server/mongodb/bin/mongo -host 127.0.0.1 -port 27017 #回车切换到数据库
>use admin #创建用户在admin数据库
>db.auth('root','rootpwd'); #先登录后验证
创建用户一定是在
admin
库下执行。如果在自己使用的数据库执行,则命令行下进入正常,用工具navicat
可以正常连接,但是php连接会报错:Authentication failed.
mongodb用户角色和权限描述
角色 | 权限描述 |
---|---|
read | 可读指定数据库中任何数据 |
readWrite | 可读写指定数据库中任何数据,包含创建,删除,重命名 |
readAnyDatabase | 可读所有数据库中任何数据【除config和local】 |
readWriteAnyDatabase | 可读写所有数据库中任何数据【除config和local】 |
dbAdmin | 可读指定数据库及对数据库进行清理,修改,压缩,获取统计信息,执行检查等操作 |
dbAdminAnyDatabase | 可读所有数据库及对数据库进行清理,修改,压缩,获取统计信息,执行检查等操作【除config和local】 |
clusterAdmin | 可对整个集群或数据库进行管理操作 |
userAdmin | 可在指定数据库创建和修改用户 |
userAdminAnyDatabase | 可在指定数据库创建和修改用户【除config和local】 |
配置文件:
## content
systemLog:
quiet: false #确保日志记录捕获尽可能多的信息安全审计
destination: file
logAppend: true
path: /www/server/mongodb/log/config.log
# Where and how to store data.
storage:
dbPath: /www/server/mongodb/data
directoryPerDB: true
journal:
enabled: true
# how the process runs
processManagement:
fork: true
pidFilePath: /www/server/mongodb/log/configsvr.pid
# network interfaces
net:
port: 17027 #更改默认27017端口
bindIp: 127.0.0.1
#operationProfiling:
#replication:
# replSetName: bt_main
security:
authorization: enabled #当authorization为disabled时,登录不需要验证账号密码。为enabled需要验证!
javascriptEnabled: false
#sharding:
# clusterRole: shardsvr
命令行快速连接
/www/server/mongodb/bin/mongo 127.0.0.1:17027/admin -u root -p root
/www/server/mongodb/bin/mongo -host 127.0.0.1 -port 17027 -u root -p root
/www/server/mongodb/bin/mongo -host 127.0.0.1 -port 17027 -u root -p root --authenticationDatabase test #指定登陆test库
开发最佳实践
mongodb://节点1,节点2,节点N/database?[options] //连接复制集
mongodb://mongos1,mongos2,mongosN/database?[options] //连接分片集
options:
maxPoolSize:连接池大小
Max Wait Time:建议设置,自动kill慢查询
Write Concern:建议majority保证数据安全
Read Concern:对于数据一致性要求高的场景适用
连接字符串节点和地址:
无论对于复制集还是分片集,连接字符串都应尽可能多提供节点地址,建议全部列出。复制集利用这些地址可更有效发现集群成员,分片集利用这些地址可更有效分散负载。
使用域名连接集群:mongodb+srv://协议
不要在mongos前使用负载均衡,让驱动处理负载均衡和自动故障恢复。
如果在mongos或复制集上层部署负载均衡,驱动无法探测哪个节点存活,无法完成自动故障恢复;驱动无法判断游标是在哪个节点创建,从而遍历游标时出错;
游标使用:
如果一个游标已经遍历完会自动关闭,如果没遍历完,则要手动close(),否则会在服务器存活10分钟(默认值)释放。造成资源浪费。
读:
数据量大的查询尽量使用索引,尽量使用覆盖索引covered indexes,避免读数据文件,使用projection减少不必要的返回字段
写:
在update语句只包含要更新字段,尽量使用批量插入来提升写性能。使用TTL自动过期日志之类的不重要数据。
文档结构:
防止使用太长字段名,浪费空间;
防止使用太深数组嵌套,超过2层操作复杂
不使用中文,标点符号等非拉丁字母作为字段。
分页:避免使用count统计和skip/limit形式分页
数据量大的查询条件不能完整命中索引时,扫描耗时。
db.test.count({'pid':1})
db.test.find({}).skip(0).limit(10);
使用查询条件+唯一排序条件
db.test.find({}).sort({_id:1}).limit(10);
db.test.find({_id:{$gt:"第一页最后一个_id"}}).sort({_id:1}).limit(10);
事务:
模型设计优于事务,尽可能用模型设计规避事,不要使用过大的事务,当必须使用事务时,尽可能让涉及事务的文档分布在同一分片上,这将有效提高效率。
网友评论