“数据库安全就像一个好密码:你可以想出超级复杂的密码,但如果你把它写在便利贴上贴在显示器上——那就白搭了。”所以我们的目标不仅是学会怎么配置安全机制,还要避开那些常见的坑,不然之前做的努力都白费。
1. 给角色分配了太多权限
开发者经常怕限制太多,结果给角色分配了超级多的权限,比如SUPERUSER或者ALL PRIVILEGES。他们的理由通常是:“万一以后用得上呢!”但权限太多的角色就是安全的大漏洞。
权限太多的例子:
GRANT ALL PRIVILEGES ON DATABASE university TO student_role;
这里student_role能完全访问数据库里的所有数据。即使本来只让它读数据,现在它能删表、改结构,甚至把管理员踢出去。
怎么避免?
创建权限最小化的角色。这叫最小权限原则。比如,只读数据的角色应该这样写:GRANT CONNECT ON DATABASE university TO student_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO student_role;
这样就很清楚student_role能干啥:连数据库、只能读。
2. 没有加密敏感数据
想象一下有个users表,密码直接明文存着:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username TEXT NOT NULL,
password TEXT NOT NULL
);
如果黑客拿到这个表,所有用户的密码都到手了。这就像把家门钥匙放门垫下面一样。
为了避免这种事, 用pgcrypto加密密码。比如:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
INSERT INTO users (username, password)
VALUES ('johndoe', pgp_sym_encrypt('secure_password', 'encryption_key'));
验证密码时可以解密:
SELECT username
FROM users
WHERE pgp_sym_decrypt(password::BYTEA, 'encryption_key') = 'secure_password';
千万别明文存敏感信息!
3. 忽略SQL注入
SQL注入一直是最常见的攻击方式之一,原因就是开发者还在用字符串拼接写SQL。比如:
DO $$
DECLARE
username TEXT := 'John';
query TEXT;
BEGIN
query := 'SELECT * FROM users WHERE username = ''' || username || ''';';
EXECUTE query;
END $$;
如果黑客把用户名换成John' OR '1'='1,结果就是users表里的所有数据都泄露了。
怎么避免? 用参数化查询:
PREPARE user_query (TEXT) AS
SELECT * FROM users WHERE username = $1;
EXECUTE user_query('John');
这样变量是安全传进去的,注入就没戏了。
4. pg_hba.conf配置不当
pg_hba.conf是按IP控制访问的主要工具。配置错了,可能让所有人都能连进来。
错误配置的例子:
host all all 0.0.0.0/0 trust
这行让任何人、任何IP都能连任何数据库,不用密码。
怎么避免? 只给特定IP开权限,用md5或scram-sha-256认证:
host university student_role 192.168.1.0/24 md5
这样student_role只能在内网用密码连。
改完pg_hba.conf后,别忘了用命令应用:
pg_ctl reload
5. ROW LEVEL SECURITY用错了
RLS很强大,但没配好或者忘了开就等于没用。比如,写了访问策略但RLS没开:
CREATE POLICY my_policy ON users
USING (username = current_user);
-- 但RLS没开!
SELECT * FROM users; -- 全部行都能查到!
怎么避免? 记得开启RLS:
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
还要检查策略效果:
SET ROLE student_role;
SELECT * FROM users; -- 只能看到符合策略的行。
6. 忽略管理员的操作
有时候数据库管理员有全部数据的权限,其实工作用不到。这就多了泄露风险,万一管理员账号被盗。
怎么避免? 分角色。管理任务用一个没数据权限的角色:
CREATE ROLE admin_role WITH LOGIN CREATEDB CREATEROLE;
数据访问用另一个权限最小的角色:
CREATE ROLE data_analyst_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO data_analyst_role;
根据任务分配角色:
GRANT admin_role TO some_user;
GRANT data_analyst_role TO another_user;
7. 日志记录不够
日志没配好,你就不会知道有啥可疑操作,等发现就晚了。
没日志的例子:
-- postgresql.conf里啥都没配
log_statement = 'none';
怎么避免? 至少开基础日志:
log_statement = 'all'
log_connections = on
log_disconnections = on
这样你能看到所有SQL、连接和断开。
还可以用pgAudit扩展做更细致的审计:
CREATE EXTENSION pgaudit;
8. 用老掉牙的认证方式
用像password这种老认证方式,安全性根本不够。
怎么避免? 换成更安全的,比如scram-sha-256:
ALTER SYSTEM SET password_encryption = 'scram-sha-256';
然后更新用户密码:
ALTER USER student_role WITH PASSWORD 'new_secure_password';
这些问题看起来都不大,但每一个都可能变成大漏洞。你要把数据库当成每个连进来的用户都很可疑。俗话说,“信任,但要验证”。现在你有了配置安全和防坑的工具,祝你好运,数据安全!
GO TO FULL VERSION