PG数据库参数log_statement设置为ddl级别及以上存在密码泄露风险

773 阅读2分钟

这是我参与8月更文挑战的第29天,活动详情查看:8月更文挑战

总结:log_statement参数,一般设置为ddl级别以上的选项,但是该方式存在风险,任何修改用户密码的操作都将被明文记录到日志中,建议在修改用户密码前,临时关闭该参数。

在生产环境中,数据库日志记录功能必不可少。

通过设置数据库参数log_statement参数来控制数据库日志记录哪些SQL,可以选择的选项有:none, ddl, mod, and all,几个选项之间的区别如下:

none:不记录任何操作语句。

ddl:只记录所有DDL操作语句。

mod:记录所有DDL以及涉及到数据修改的语句。

all:记录所有操作语句。

例如下边这种情况就是设置数据库参数log_statement为ddl的状态:

postgres=# show log_statement;
 log_statement
---------------
 ddl
(1 row)
postgres=#  select * from pg_file_settings where name ='log_statement';
                  sourcefile                  | sourceline | seqno |     name      | setting | applied | error
---------------------------------------------+------------+-------+---------------+---------+---------+-------
 /postgres/data/postgresql.auto.conf |         10 |    31 | log_statement | ddl     | t       |
(1 row)

如果我们执行一个修改密码的操作,因为此类操作属于ddl语句范畴,因此

postgres=# alter user postgres encrypted password 'postgres';
ALTER ROLE

数据库日志记录如下:

2018-04-19 14:55:00.342 CST,"postgres","postgres",3440,"[local]",5ad83cd7.d70,3,"idle",2018-04-19 14:53:11 CST,2/7,0,LOG,00000,"statement: alter user postgres encrypted password 'postgres';",,,,,,,,,"psql"

可以看到,执行的修改密码操作被记录到了数据库日志中,而且密码以明文形式进行显示。

综上所述,建议在修改密码或者其他涉密操作之前,临时关闭该参数:

postgres=# set log_statement = 'none';
SET
postgres=# alter user postgres encrypted password 'postgres';
ALTER ROLE

该参数仅在当前会话生效,断开连接或退出登录后即失效,恢复为数据库参数设置值。

当然,这就有一个问题,就是如果有个懂行的人想干坏事,在干坏事之前先执行了set log_statement = 'none';,就会导致这些操作从日志当中无法被追踪。

所以如果是出于安全考虑,需要对这些操作进行专业而正式的审计,而不是日志记录这种辅助方法。可以采用第三方的一些插件statement,比如pgaudit。