最小权限原则不能阻止sql注入发生,但能限制其危害范围;需结合参数化查询、严格sql_mode、显式列级授权及定期权限评审,才能有效遏制攻击后果。

最小权限原则不能阻止SQL注入发生,但能决定它爆出来后能干成什么事——权限越小,攻击者拿到的“战利品”越少,甚至查不到表名。
SQL注入本质是借号执行,不是直接提权
注入代码最终是以数据库账号身份运行的。如果这个账号只有 SELECT (id, name) 权限,那 UNION SELECT @@version, user(), database() 就会报错或只返回空值;INSERT INTO users、DROP TABLE logs 更是直接被拒绝。
- MySQL 中用
SHOW GRANTS FOR CURRENT_USER()可立刻看到当前上下文能做什么 - PostgreSQL 里
\z public.active_users能查视图是否真隔离了基表访问 - SQL Server 的
SELECT IS_SRVROLEMEMBER('sysadmin')和IS_MEMBER('db_datareader')必须都为 0 才算安全
列级授权比表级更关键,尤其对敏感字段
很多团队只做到 GRANT SELECT ON myapp.users TO 'web',这等于把整张表敞开——密码哈希、手机号、身份证号全在射程内。真正有效的做法是显式限定字段:
- MySQL:必须写
GRANT SELECT (id, username, email) ON myapp.users TO 'web_ro'@'%',不写字段列表就是全列授权 - PostgreSQL:用视图封装 +
WITH CHECK OPTION防绕过,比如CREATE VIEW login_view AS SELECT username, password_hash FROM users WHERE status = 'active' WITH CHECK OPTION - SQL Server:列级权限需通过
GRANT SELECT ON OBJECT::users(username, password_hash) TO app_user显式授予,且要确认db_datareader角色没覆盖掉它
三个最容易被忽略的权限陷阱
配得再细,踩中以下任一坑,前面所有操作都归零:
- MySQL 关闭了严格模式:
sql_mode缺失STRICT_TRANS_TABLES时,SELECT 1,2 FROM dual可绕过UNION字段数校验,强行拖出系统表 - PostgreSQL 的
publicschema 默认可读:REVOKE USAGE ON SCHEMA public FROM PUBLIC不执行,攻击者就能跑SELECT table_name FROM information_schema.tables扫库 - 账号密码明文写在配置文件里:哪怕权限只剩
SELECT,服务器一旦被拿 shell,cat config.yml | grep password就连库成功
最小权限不是上线前配一次就完事的事——每次新增一个报表接口、加一个搜索字段、改一次 JOIN 表,都要重走一遍权限评审:这个 SQL 真的需要查 syslogins?那个导出功能真的要 FILE 权限?别让“先开了再说”变成生产环境里的永久后门。











