数据库账号严禁授予create、drop、file等高危权限,即使测试环境亦不可开启;grant必须限定库、表、字段三级范围,禁用on .;需启用sql严格模式并撤销postgresql public schema的默认usage权限。

数据库账号不该有 CREATE、DROP、FILE 权限
哪怕只给测试环境,也别开这些权限。SQL 注入一旦触发,CREATE 和 DROP 能直接删表或建后门表;FILE 更危险——攻击者可用 SELECT ... INTO OUTFILE 把密码哈希导出到 Web 目录,或用 LOAD DATA INFILE 读取服务器文件(如 /etc/passwd)。MySQL 默认禁用 FILE,但有些运维为“方便备份”手动开启,这等于给注入留了后门。
GRANT 时必须限定库、表、字段三级范围
别写 GRANT SELECT ON *.* TO 'app',这是最常见错误。真实场景中:
- 商品列表接口只需查
products表的id、name、price字段 → 用列级权限:GRANT SELECT(id, name, price) ON myshop.products TO 'web_app'@'%'; - 登录验证只比对
username和password_hash→ 建视图隔离:CREATE VIEW login_view AS SELECT username, password_hash FROM users;,再授SELECT给该视图 - 后台导出需跨 3 张表 → 不要直接授多表权限,建角色:
CREATE ROLE export_role;,GRANT SELECT ON sales, customers, orders TO export_role;,最后GRANT export_role TO 'report_user'@'%';
MySQL 严格模式和 PostgreSQL public schema 是隐形陷阱
权限配得再细,这两处一松,前面全白干:
- MySQL 5.7+ 默认启用
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,但旧项目常在配置里关掉。一旦sql_mode缺失严格项,攻击者就能用SELECT 1,2,3 FROM dual绕过 UNION 字段数校验,强行拖information_schema里的表名 —— 检查命令:SELECT @@sql_mode;,确保返回含STRICT_TRANS_TABLES - PostgreSQL 的
publicschema 默认对所有用户可读。即使你没显式GRANT,攻击者仍能执行SELECT table_name FROM information_schema.tables扫库 —— 必须补一句:REVOKE USAGE ON SCHEMA public FROM PUBLIC;
密码不能硬编码,权限变更必须随功能上线同步评审
最小权限不是设一次就完事。每次加新接口,都要重问一句:“这个接口到底要哪几张表、哪几列、什么操作?”
- 配置文件里写死
db_password = 'xxx'?服务器被拿 shell 后,攻击者直接 cat 配置就能连库 —— 必须用运行时注入(如 Kubernetes Secret 挂载)或密钥服务(HashiCorp Vault) - 上线一个“用户导出 Excel”功能,开发顺手给了
SELECT全表权限,但实际只要name、email、created_at三列 → 权限收紧必须纳入上线 checklist,由 DBA 或安全同学签字确认
最容易被忽略的,是权限和代码逻辑的实时对齐。今天给的 SELECT 权限,明天接口改用 JOIN 查关联表,却忘了加对应表权限 —— 这时应用报错,但攻击者可能正利用报错信息反推表结构。











