Union注入能直接拖取数据库任意表数据,因其利用页面回显位+UNION SELECT拼接恶意查询,只要列数、类型兼容且账号具备SELECT权限(如误配root或全局权限),即可明文输出敏感信息;收紧至最小必要表/字段级权限可将其降级为局部泄露。

Union注入能直接绕过应用层逻辑,把数据库里任意表的数据“拖”到前端页面上——只要攻击者猜对列数、类型和权限,UNION SELECT 就是数据库的后门钥匙。
为什么UNION SELECT 一击即中?
它不依赖报错或盲注,只要页面回显 SQL 查询结果(比如搜索页、商品列表、用户信息页),攻击者就能用 UNION SELECT 拼接自己的查询,让数据库“主动吐数据”:
- 原始查询可能只查
title, author两列,攻击者就构造UNION SELECT username, password FROM users,前提是列数、类型兼容 - 不需要触发错误,也不需要时间差判断,响应体里直接出现用户名密码明文
- 一旦数据库账号有
SELECT权限,information_schema表可查,表名、字段名、数据全链路可枚举
仅靠SELECT 权限就足够危险?
是的。绝大多数业务场景只要读取数据,数据库账号就必须有 SELECT 权限——但问题在于:这个权限不该是“全局”的。
常见错误配置:
- 应用使用
root或dbadmin账号连库,哪怕只执行SELECT * FROM articles,它也能顺手SELECT * FROM users - 账号被授予
SELECT ON *.*,等于把整个数据库的只读门禁卡交给了攻击者 - 没按业务模块隔离库/表权限,例如后台管理库和用户中心库共用一个账号
后果就是:UNION SELECT 不需要提权、不触发告警、不写日志(除非开启通用查询日志),一次成功注入 = 全量用户表导出。
怎么限制SELECT 权限才真正有效?
核心原则:账号只能访问它“必须访问”的那几张表,且不能跨库。
实操要点:
- 为每个业务功能创建独立数据库账号,例如
web_search@'%'只能SELECTsearch_index和articles表 - 显式收回全局权限:
REVOKE SELECT ON *.* FROM 'web_search'@'%';,再逐表授权:GRANT SELECT(id,title,slug) ON myapp.search_index TO 'web_search'@'%'; - 禁用
information_schema的非必要访问:REVOKE SELECT ON information_schema.* FROM 'web_search'@'%';(MySQL 8.0+ 支持更细粒度控制) - 配合应用层约束:即使权限收紧,仍要避免拼接用户输入进 SQL,否则
UNION SELECT仍可能命中已授权的表
权限收紧后,UNION 注入真的失效了吗?
没有完全失效,但攻击面急剧收窄:
- 如果账号只能查
products表,攻击者最多拖走商品数据,拿不到users或orders - 若字段权限也做了限制(如只授权
name,price),UNION SELECT id,password FROM users会因权限拒绝直接报错,无法执行 - 最关键的是:它把“一次注入=全库沦陷”降级为“一次注入=局部数据泄露”,为应急响应争取时间
真正容易被忽略的点是:权限策略必须和应用部署环境强绑定。测试库开全权限没问题,生产库账号若沿用测试配置,SELECT 限制就形同虚设。

















