sql-labs_less1-6



概述

  操作环境。

  常见功能点:查询框。


判断注入点和闭合方式(待)

  默认前提: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.schemataschema_name顶级结构无需where
存储所有表信息information_schema.tablestable_name所属数据库table_schema
存储 所有字段信息information_schema.columnscolumn_name所属表table_name
基础查询语句
查库名查表名、列名查列值
select xx from xxselect xx from xx where xx=xxselect column from table



双查询注入(5-6关)

  条件:程序输出数据库报错信息。
报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。
  双查询注入原理:利用主键重复,人为制造错误条件,使查询结果出现在错误信息。

数据库报错注入版本限制-补充
报错函数数据库版本 (只验证了5.0.96、5.1.60、5.5.29、5.7.26、8.0.12)
extractvalue5.1.60、5.5.29、5.7.26、8.0.12
updatexml5.1.60、5.5.29、5.7.26、8.0.12
floor5.0.96、5.1.60、5.5.29、5.7.26
exp5.5.29
GeometryCollection5.1.60、5.5.29
linestring5.1.60、5.5.29
polygon5.1.60、5.5.29
multipoint5.1.60、5.5.29
multipolygon5.1.60、5.5.29
multilinestring5.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 usersMySQL报错-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
这篇文章总结得相对来说比较全面,可以作为参考补充遗漏的地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值