CodeGym /课程 /SQL SELF /配置安全性时常见的错误以及如何避免它们

配置安全性时常见的错误以及如何避免它们

SQL SELF
第 48 级 , 课程 4
可用

“数据库安全就像一个好密码:你可以想出超级复杂的密码,但如果你把它写在便利贴上贴在显示器上——那就白搭了。”所以我们的目标不仅是学会怎么配置安全机制,还要避开那些常见的坑,不然之前做的努力都白费。

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开权限,用md5scram-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';

这些问题看起来都不大,但每一个都可能变成大漏洞。你要把数据库当成每个连进来的用户都很可疑。俗话说,“信任,但要验证”。现在你有了配置安全和防坑的工具,祝你好运,数据安全!

1
调查/小测验
数据加密入门第 48 级,课程 4
不可用
数据加密入门
数据加密入门
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION