文章目录
概述
操作环境。
常见功能点:查询框。
判断注入点和闭合方式(待)
默认前提:id=1返回数据非空。以数字型注入为例。
判断依据:输入语句是否被程序执行
判断方式 | 用户输入 | 页面结果 | 原因 |
---|---|---|---|
单引号报错 | id=1’ | 输出数据库报错信息 | SQL语法错误 |
反斜杠报错- | id=1\ | 输出数据库报错信息 | SQL语法错误 |
加减运算 | id=1,id=2-1 | 二者返回页面相同 | 执行运算语句 |
真假语句and | 分别输入id=1 and 1=1,id=1 and 1=2 | 前者返回数据,后者数据为空 | ? |
疑问:
真假语句的返回值是Ture、False的话,怎么返回数据?
mysql对单双引号的识别敏感吗?
手测:使用burpsuite爆破判断语句字典,分析爆破结果对应的情况。
联合查询(1-4关)
1-4关卡的不同之处在于字符的闭合方式,分别为数字无闭合、单引号’ 、’) 、’")
Union查询用法
第一条查询语句结果为空时,会返回第二条查询语句的结果。
Union内部的select语句必须拥有相同数量的列。
注意,Union注入必须有回显位,即程序输出查询结果,否则获取不到信息。
order by排序
默认按照某列的升序对结果集进行排序,可以传递列名或列序号。
比如select * from tables order by id
比如select * from tables order by 4(第四列)
输入order by 4,返回如Unknown column ‘4’ in ‘order clause’,说明表中没有第四列。
利用列排序语句order by,可以得知列数,从而进行Union select查询。
MySQL系统函数
系统函数 | 用途 |
---|---|
version() | 返回数据库版本 |
user() | 返回数据库当前用户 |
database() | 返回当前使用的数据库名称 |
group_concat() | 拼接列数据,作为一行显示(自带逗号) |
information_schema数据库
information_schema是MySQL自带数据库用于存储数据库元数据(关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等,只是一个视图且不可修改。
通过这个数据库,我们可以查询所有的数据库名、表名和字段名。
用途 | 表名 | 列名 | 查询定位 |
---|---|---|---|
存储所有数据库信息 | information_shcema.schemata | schema_name | 顶级结构无需where |
存储所有表信息 | information_schema.tables | table_name | 所属数据库table_schema |
存储 所有字段信息 | information_schema.columns | column_name | 所属表table_name |
基础查询语句
查库名 | 查表名、列名 | 查列值 |
---|---|---|
select xx from xx | select xx from xx where xx=xx | select column from table |
双查询注入(5-6关)
条件:程序输出数据库报错信息。
报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。
双查询注入原理:利用主键重复,人为制造错误条件,使查询结果出现在错误信息。
数据库报错注入版本限制-补充
报错函数 | 数据库版本 (只验证了5.0.96、5.1.60、5.5.29、5.7.26、8.0.12) |
---|---|
extractvalue | 5.1.60、5.5.29、5.7.26、8.0.12 |
updatexml | 5.1.60、5.5.29、5.7.26、8.0.12 |
floor | 5.0.96、5.1.60、5.5.29、5.7.26 |
exp | 5.5.29 |
GeometryCollection | 5.1.60、5.5.29 |
linestring | 5.1.60、5.5.29 |
polygon | 5.1.60、5.5.29 |
multipoint | 5.1.60、5.5.29 |
multipolygon | 5.1.60、5.5.29 |
multilinestring | 5.1.60、5.5.29 |
MySQL系统函数
拼接函数 | 用途 |
---|---|
concat(str1,分隔符,str2,Separator,str3) | 拼接行数据 |
concat_ws(分隔符,str1,str2,str3) | 拼接行数据 |
group_concat(列名) | 拼接列数据,把逗号作为分隔符 |
报错注入floor(rand()*2)
双查询注入相关函数
函数功能 | 函数名称 | 用途 |
---|---|---|
随机函数 | rand() | 用于返回 [0,1)之间的随机数,范围不被参数影响 |
- | rand(0) | 接收整数参数作为随机数的种子,种子固定则随机数(列)固定 |
取整函数 | floor(float) | 向下取整 |
组合 | floor(rand(14)*2) | rand(14)随机数列相同,*2使范围 [0,2),floor限定值0或1 |
计数函数 | count() | 常用于统计行数,如select count(*) from table |
分组语句 | group by | 根据列名对查询结果进行分组,值相等的为一组 |
组合 | select 列,count(*) from表 group by 列 | 统计表的某id有多少行数据,如某人借了几本书(临时表) |
floor(rand(14)*2)产生的随机数列,前四位是:
1,0,1,0
考虑现实场景
想象一个现实场景,我们需要查询每个读者借了多少本书。
查询语句 | 作用 |
---|---|
select * from users | 查询所有的借阅记录,形式如姓名-书籍,不便统计 |
select count(*) from users | 查询表中的记录数量 |
select username,count(*) from users | MySQL报错-ERROR 1140 : In aggregated query without GROUP BY |
select username,count(*) from users group by username | 统计每个username有多少条记录(如下图) |
程序完成这个统计的具体过程是什么?师傅们推测:
MySQL建立一张临时表,有group_key和tally两个字段,其中group_key具有Unique约束。
建临时表后开始扫描要查询的表,查到第一条记录username后,到临时表对比是否存在这个username,如果无则添加该条记录,如果有则对应的tally字段加1,直到扫描结束。
理解核心语句
核心语句:select floor(rand(14)*2) c, count(*) from information_schema.columns group by c;
首先要理解count(*)和group by的组合。程序执行统计语句,建立临时表。
第一次扫描,执行语句select floor(rand(14)*2 c,count(*) from table group by c,运算floor(rand(14)*2,执行select 1,得到查询结果1。查看临时表,发现没有group_key值为1的记录,把查询结果添加进临时表,再次运算floor(rand(14)*2,得到0,所以第一次插入的是0。
(如果插入时不再执行运算,就不会导致重复插入,可能就没有这个bug了)
第二次扫描,执行select语句,查询结果为1。查临时表,发现没有该记录。执行插入操作,执行运算得到正在插入的记录为0,与第一次插入的记录重复,违背Unique约束,程序中断并报错~
更重要的是,程序报错会把子查询的结果一起显示出来。
执行语句:select floor(rand(14)*2) c, count(*) from information_schema.columns group by c;
利用
(1)执行如下语句,期望返回user信息。但理论上不能同时统计两列,所以需要拼接函数concat(),如下是报错情况:
select user,floor(rand(14)*2) c,count(*) from users group by c;
(2)使用拼接函数concat()、子查询语句:
成功:select concat((select user from users limit 1),’-’,floor(rand(14)*2)) c,count(*) from users group by c;
(3)值得注意的是,如果不加limit 1的话,会报错“子查询返回结果超过1行”。
但只有第1行数据肯定不够,要想获得全部数据,可以使用limit遍历,也可以在子查询中使用group_concat()拼接列:
成功执行:
select concat((select group_concat(user) from users),’-’,floor(rand(14)*2)) c,count(*) from users group by c;
Xpath语法错误
利用Xpath语法错误来进行报错注入,主要利用extractvalue()和updatexml()俩函数。
使用条件:mysql版本>5.1.5
extractvalue()
函数原型:extractvalue(xml_document,Xpath_string)
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:Xpath_string是xpath格式的字符串
作用:从目标xml中返回包含所查询值的字符串
报错原因:第二个参数是要求符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里,因此可以利用。
核心Payload:
id=‘and(slect extractvalue(‘anything’,concat(’~’,(select语句))))
id=‘and(select extractvalue(‘anything’,concat(’~’,(系统变量))))
分隔符:一般用~作为分隔符,16进制是0x7e。’~'可以换成’#’、’$‘等不满足xpath格式的字符。
把+、-号作为分隔符时,报错不显示查询信息或显示不完全。
查询结果长度:extractvalue()能查询字符串的最大长度为32,如果我们想要的结果超过32,就要用substring()函数截取或limit分页,一次查看最多32位。
Payload示例:
id=‘and(select extractvalue(1,concat(’~’,(select database()))))
id='and(select extractvalue(1,concat(0x7e,@@version)))
id='and(select extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))))
updatexml
函数原型:updatexml(xml_document,xpath_string,new_value)
正常语法:updatexml(xml_document,xpath_string,new_value)
第一个参数:xml_document是string格式,为xml文档对象的名称 第二个参数:xpath_string是xpath格式的字符串
第三个参数:new_value是string格式,替换查找到的负荷条件的数据作用:改变文档中符合条件的节点的值。
核心Payload:
id=‘and(select updatexml(“anything”,concat(’~’,(select语句())),“anything”))
Payload示例:
‘and(select updatexml(1,concat(’~’,(select database())),1))
'and(select updatexml(1,concat(0x7e,@@database),1))
与联合查询的部分比较
关键字 | 说明 |
---|---|
union | 可以不使用Union关键字, |
select | 查看系统变量,可以不使用select |
空格space | 在字符型注入情况下,可以不使用空格。 |
小结
参考
《渗透之——SQL注入点检测方法》,2018-12
文章地址https://blog.csdn.net/l1028386804/article/details/84929699
《MySQL 中的 information_schema 数据库》,2018-04
文章地址https://blog.csdn.net/kikajack/article/details/80065753
《SQLi-Labs1~65关通关攻略》, 2019-10
文章地址https://blog.csdn.net/ga421739102/article/details/102815331
《concat和group_concat的区别》,2019-12
文章地址https://blog.csdn.net/xiao__jia__jia/article/details/103663284
《浅析MySQL中concat以及group_concat的使用》,2018.06
文章地址https://www.jianshu.com/p/43cb4c5d33c1
《Mysql中Double Injection原理浅析》,2019-04
文章地址https://blog.csdn.net/wn314/article/details/89297560
《sql基于报错注入rand() floor() count()》,2020-09
文章地址https://blog.csdn.net/qq_45200829/article/details/104807806
《sql注入之报错注入》,2019-06
文章地址https://blog.csdn.net/silence1_/article/details/90812612
《SQL注入之五大注入手法》,2019-10
文章地址https://blog.csdn.net/ga421739102/article/details/102817334
这篇文章总结得相对来说比较全面,可以作为参考补充遗漏的地方。