一、认证安全
1、用户密码安全存储
如果 password_encryption=md5
,但创建用户时未使用 ENCRYPTED
,密码将以明文存储。
格式:
CREATE ROLE name [WITH option [...]] [ENCRYPTED | UNENCRYPTED] PASSWORD 'password';
2、用户密码更换周期
使用合理的密码更换周期:
- 示例:ALTER ROLE rep VALID UNTIL ‘2028-04-18 00:09:07’;
- 配合 crontab 或监控工具进行密码到期提醒。
3、用户密码复杂度策略
确保已编译 passwordcheck,如未编译,请在源码的 contrib
目录中编译。
创建或修改用户密码时,强制密码复杂度和唯一性:
- 示例:限制密码长度、包含数字、字母、大小写、特殊字符,排除常见弱密码。
4、防止密码被记录到日志中
- 创建用户时:
- 使用createuser命令行工具中的-W选项提示输入密码。
- 修改用户密码时:
- 使用 pg_md5 工具生成密码,并在 psql 中用 ALTER ROLE 填入生成的 md5 值。
- 使用域认证或第三方认证:
密码策略交由第三方管理,避免在数据库中直接管理密码。
5、处理 pg_stat_statements 模块记录SQL或用户密码信息
创建用户和修改用户密码后,调用 pg_stat_statements_reset()清除记录的SQL;
或者配置 pg_stat_statements.track_utility=off,避免记录 DDL 语句。
6、客户端认证控制
pg_hba.conf 配置项(详见用户手册)
安全建议:
- 禁用 trust 认证方法
- 超级用户 postgres仅允许本地连接
- 将 dbname、username、IP 限制到最小,授权用户只能从授权IP连接授权数据库
- 使用最小权限范围,避免 all、0.0.0.0/0 等大范围授权
- 密码更换周期
- 使用 md5 认证,确保网络传输密码是 md5+随机字符 的加密密文
7、密码方式method认证过程的安全事项
未使用 SSL 时,避免使用 password 认证以防密码明文传输。
建议在 PG 13 以上版本中使用 SCRAM
认证(推荐),否则使用 md5
。
延迟反馈密码错误消息,防止暴力破解和 DDoS 攻击。
二、数据加密
1、数据传输加密
使用加密传输,例如OPENSSL
示例:设置数据传输安全ssl
端口安全性 :
修改默认端口,防火墙策略 ,ssh隧道技术
2、字段存储加密
将敏感数据加密后存储在数据库中,即使数据泄露,只要加解密方法未泄露,也相对安全。
建议加解密方法放在应用端,或加密在数据库端,解密在应用端。pgcrypto 模块提供密码函数。
示例:使用 pgcrypto
加密敏感数据。
create extension pgcrypto;
计算hash值的函数。
digest(data text, type text) returns bytea
digest(data bytea, type text) returns bytea
type为算法.支持 md5, sha1, sha224, sha256, sha384, sha512。
如果编译postgresql时有了with-openssl选项, 则可以支持更多的算法。
三、权限控制
1、用户权限最小化
使用超级用户创建数据库、所需 schema、表、索引、函数。
创建应用账号,并赋予其数据库和 schema 的使用权限。
应用账号最容易暴露,也是最危险的。其权限越大,应用程序被攻击后的破坏性越大。
授予应用账号 SELECT
、INSERT
、UPDATE
、DELETE
以及函数的 EXECUTE
权限,严控 DROP
、TRUNCATE
、REPLACE
等权限。
通过列权限或视图限制应用账号权限。
grant connect on database dbname to approle;
grant usage on schema sch_name to approle;
2、回收数据库,schema,language,应用对象的public权限。
revoke all on database dbname from public;
revoke all on schema sch_name from public;
revoke all on language plpgsql from public;
revoke all on table ... from public;
revoke all on function ... from public;
3、函数语言安全
回收函数语言的public权限,以及普通用户的权限,普通用户不能创建函数
revoke all on language plpgsql from public;
revoke all on language plpgsql from app_role;
4、行级安全RLS (Row Level Security)
限制普通用户只能操作符合特定条件的记录。
行级安全策略(9.5版本后新增),不同用户可以看到表中不同的数据,控制级别为行级。
CREATE POLICY name ON table_name
[ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ];
5、触发器控制
通过事件触发器禁止应用账号执行 DDL,防止被攻击后 DROP 或 TRUNCATE 删除对象或清空数据。
防止无条件的 DELETE、UPDATE,在需保护的表中新增一条 dummy 记录,并创建行触发器,当此记录被更新或删除时抛出异常。
四、防恶意攻击
1、视图攻击
用户利用PostgreSQL的优化器原理,创建成本极低的函数,在函数中获取视图限制外的隐藏内容。
如果用户没有创建函数的权限,用户就无法利用这个原理,或者使用安全栅栏来弥补。
2、密码暴力破解
目前可以通过密码错误延迟认证(auth_delay)来增加暴力破解需要的时间
3、防止普通用户通过陷阱进行攻击
参考文档《PostgreSQL 安全陷阱 - 利用触发器或规则,结合security invoker函数制造反噬陷阱》
4、防止SQL注入
应用层应该有SQL注入预防手段,例如使用简单的过滤器,使用绑定变量等手段。
以下攻击示例只要检查变量类型, 拒绝请求就不会有问题
statement := “SELECT FROM userinfo WHERE id = “ + a_variable + “;”
如果a_variable 不做任何判断, 传入 1;DROP TABLE users
那么SQL变成 :SELECT FROM userinfo WHERE id=1;DROP TABLE users;
五、安全审计
1、审计功能,一般是用于排查问题,也是一种举证的手段。
2、审计的主要通过记录日志来实现
3、审计功能建议考虑以下内容
跟踪 postgresql.conf
配置变更:
- 使用标准日志工具
log_statement = all
。
跟踪表中记录被哪个用户修改或插入: - 使用
hstore
插件和触发器。
跟踪表的创建时间和定义修改时间: - 使用
pgAudit
插件获取详细的会话和对象审计日志记录。
4、SQL审计
记录某DBA用户的所有SQL,并审计业务用户的DDL以减少日志输出。
配置 postgresql.conf
参数 log_statement
实现。
示例:记录某用户的所有SQL。
5、表对象的审计
PostgreSQL 可通过 log_statement=all
实现日志审计,但不够详细。pgAudit
扩展提供更详细的会话和对象审计日志。
注意:若删除并需重建 pgAudit
扩展,必须先取消设置 pgaudit.log
,否则会报错。
6、会话或对象审计日志记录
对象触发器:权限限制,数据审计
在数据库应用中,需跟踪某些表的记录更改,如删除、增加、更新。跟踪信息包括:旧记录值、新记录值、变更时间、操作用户等。可用触发器实现跟踪。
使用 hstore
类型存储变更前后的行信息,并利用 each
函数方便提取原始值。
六、对象安全控制
1、约束:一般用于控制数据的安全,如 check (balance >=0)
2、视图和物化视图:一般被用于控制列或者值的被查询安全
3、查询列
4、条件筛选行
5、加密列
6、防范视图攻击
七、版本升级
PostgreSQL 社区更新频繁,几乎每天都有修复补丁、功能增强或性能提升。大家可以根据漏扫结果进行版本升级和加固。
- 小版本升级:通常仅需跟随小版本升级。如有重大安全漏洞,补丁发布后会快速跟进小版本。若无发布小版本,说明无重大漏洞。
- 大版本升级:包含大量新功能,需注意与应用相关的修改和模块更新。
数据库升级分为两种:
- 小版本迭代
- 大版本(主版本)升级
例如:PostgreSQL 14.12 中,14 是主要版本,12 是次要版本。
八、外界环境安全
当然这些一般不需要我们去操心,是云网管理员、应用管理员和主机管理员负责的。
1、应用程序是否安全?
2、中间件是否安全?
3、数据库所在操作系统是否安全?
4、数据库所在服务器是否安全?
5、存储安全,存储是否在安全的地方,有没有硬盘被拔掉的风险?
6、网络安全,如机架交换机,未插网线的端口是否禁用了,是否做了MAC地址过滤或绑定?
7、机房安全?
九、资源控制
1、 资源控制举例
- 控制连接数和活动连接数
- 限制 SQL 执行时间
- 限制锁等待时间
- 控制事务空闲时间
2、并发用户连接的限制
pg_hba.conf可严格限制地址,确保用户来源可信。
- 配置用户最大并发连接数。
- PostgreSQL 默认具有连接超时策略。
- 配置参数 connect_timeout(秒计,十进制整数字符串)。
- 0 或未指定表示无限等待。不建议使用低于 2 秒的超时时间。
十、可靠性参数优化建议
1、事务返回成功前,事务日志写入磁盘,synchronous_commit = on
能够保证数据的一致性,但是不能保证数据完全不丢失
2、fsync = on ,full_page_writes = on
3、存储Cache写机制write-through,write-back
关闭磁盘的write cache
只允许有断电保护的write cache
4、开启归档,并且有良好的备份策略
5、异地容灾,如流复制