数据库是现代信息系统的核心,存储着大量敏感数据:用户信息、财务数据、商业机密等。数据库的安全直接关系到整个系统的安全。如果数据库被攻破,攻击者可能访问、修改或删除大量敏感数据。

数据库是攻击者的主要目标,因为数据库通常包含最有价值的数据。数据库安全漏洞可能导致大规模数据泄露,造成严重的经济和声誉损失。
这一节课我们将讨论数据库访问控制、SQL注入、推理攻击、聚合问题、数据库完整性、审计等核心概念。
数据库访问控制决定谁可以访问哪些数据,以及可以执行哪些操作(SELECT、INSERT、UPDATE、DELETE等)。数据库访问控制是数据库安全的基础。
数据库系统使用用户(User)和角色(Role)来管理访问控制。用户是数据库账户,角色是权限的集合。用户可以被授予角色,从而获得角色的所有权限。
这种设计简化了权限管理。不需要为每个用户单独授予权限,只需要将用户添加到相应的角色即可。当权限需要修改时,只需要修改角色,所有拥有该角色的用户都会自动获得新权限。
角色是数据库权限管理的关键。合理设计角色结构,可以大大简化权限管理,也更容易维护和审计。
表级权限控制用户可以对哪些表执行哪些操作。常见的表级权限包括:
表级权限提供了基本的访问控制,但粒度较粗。如果用户只需要访问表中的部分数据,表级权限可能过于宽松。
行级安全(Row-Level Security,RLS)允许基于数据内容动态决定访问权限。用户可能只能看到满足特定条件的行,比如只能看到自己创建的记录,或者只能看到特定状态的数据。
|-- PostgreSQL行级安全策略示例 CREATE POLICY user_isolation ON documents FOR ALL TO app_user USING (owner_id = current_user_id());
这个策略确保用户只能访问自己拥有的文档,即使他们被授予了访问documents表的权限。
行级安全提供了细粒度的访问控制,特别适合多租户应用。但行级安全也可能影响性能,因为需要为每个查询检查策略。
列级安全允许控制用户可以看到哪些列。某些列可能包含敏感信息(如密码、信用卡号),不应该被所有用户访问。
列级安全可以通过视图(View)实现。创建一个视图,只包含用户应该看到的列,然后授予用户访问视图的权限,而不是访问原始表的权限。
|-- 创建视图,隐藏敏感列 CREATE VIEW user_public_info AS SELECT id, username, email, created_at FROM users; -- 授予用户访问视图的权限 GRANT SELECT ON user_public_info TO app_user;
SQL注入是最常见的数据库安全漏洞之一。攻击者通过在输入中注入SQL代码,来执行未授权的数据库操作。
SQL注入发生在应用程序将用户输入直接拼接到SQL查询中时。如果用户输入包含SQL代码,这些代码可能被数据库执行。
|# 危险的代码:直接拼接用户输入 def get_user(username): query = f"SELECT * FROM users WHERE username = '{username}'" # 如果username是 "admin' OR '1'='1" # 查询变成: SELECT * FROM users WHERE username = 'admin' OR '1'='1' # 这会返回所有用户 return execute_query(query)
如果攻击者输入 admin' OR '1'='1,查询会变成 SELECT * FROM users WHERE username = 'admin' OR '1'='1',这会返回所有用户,因为 '1'='1' 总是为真。
SQL注入是最危险的数据库安全漏洞之一。攻击者可能通过SQL注入读取、修改或删除数据,甚至获得数据库的完全控制。

防御SQL注入的关键是使用参数化查询(Prepared Statements)。参数化查询将用户输入作为参数传递,而不是直接拼接到SQL查询中。
|# 安全的代码:使用参数化查询 def get_user(username): query = "SELECT * FROM users WHERE username = ?" # 使用参数化查询,username作为参数传递 # 即使username包含SQL代码,也不会被执行 return execute_query(query, (username,))
参数化查询确保用户输入被当作数据而不是代码处理,防止SQL注入。
其他防御措施包括:
推理攻击是数据库安全中的独特问题。攻击者可能通过合法的查询来推断敏感信息,即使他们无法直接访问敏感数据。
推理攻击利用数据库查询的确定性。如果攻击者可以执行查询并观察结果,他们可能通过多次查询来推断敏感信息。
例如,假设攻击者想知道某个员工的工资。他们可能无法直接查询工资,但可以查询:
推理攻击是数据库安全中的独特挑战。即使访问控制正确,攻击者仍然可能通过合法的查询来推断敏感信息。防御推理攻击需要结合多种方法。
聚合问题是推理攻击的特殊情况。攻击者可能通过聚合查询(如COUNT、SUM、AVG)来推断敏感信息。
假设一个数据库包含医疗记录,每个记录包含患者的疾病信息。攻击者可能无法直接查询某个患者的疾病,但可以查询:
小计数问题(Small Count Problem)是聚合问题的一个例子。如果聚合查询的结果很小(如只有1个),攻击者可能推断出这1个记录的信息。
例如,如果查询"有多少女性患者患有某种罕见疾病"返回1,攻击者可能通过其他查询(如年龄、地区等)来识别这1个患者。
数据库完整性确保数据不被未授权修改,审计记录数据库的操作,用于安全审计和合规性。

数据库审计记录数据库的操作,包括:
审计日志必须受到保护,防止被修改或删除。可能的方法包括:
数据库审计是安全事件调查和合规性的关键。保护审计日志的完整性,确保审计日志的可用性,是数据库安全设计的重要部分。
数据库加密提供额外的数据保护。即使攻击者获得了数据库文件,如果没有密钥,也无法读取加密的数据。
不同的加密方式有不同的优缺点。TDE提供了透明的加密,但密钥管理是关键。列级加密提供了细粒度控制,但管理复杂。应用层加密提供了最强的控制,但需要修改应用程序。
数据库备份是数据保护的重要部分。但备份本身也可能成为安全风险,如果备份文件被未授权访问,数据可能泄露。
数据库恢复过程也可能成为安全风险。恢复操作可能:
恢复操作应该受到严格控制,只有授权人员可以执行恢复操作,恢复操作同样也应该被审计,确保恢复操作的正确性和合规性。
数据库安全是信息系统安全的关键。数据库访问控制决定谁可以访问哪些数据,SQL注入是最常见的数据库安全漏洞,推理攻击和聚合问题是数据库安全中的独特挑战,数据库完整性和审计确保数据的正确性和可追溯性。
在下一个部分中,我们将讨论网络安全,理解网络层面的安全防护。