DVWA练习之SQL Injection

DVWA练习之SQL Injection

本博客将记录在web安全问题中一种常见的漏洞——“SQL注入”漏洞的实践演练。首先阐述SQL注入漏洞的概念,原理,最后展示基于DVWA的各种等级的SQL注入漏洞。


SQL注入

概念:指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。SQL注入漏洞的危害是巨大的,常常会导致整个数据库被“脱裤”,尽管如此,SQL注入仍是现在最常见的Web漏洞之一。
当我们手动进行SQL注入是常有以下步骤:

1.判断是否存在注入,确定数据库POC

2.确定SQL查询语句中的字段数

3.确定显示的字段顺序

4.获取当前数据库

5.获取数据库中的表

6.获取表中的列名

7.下载数据


DVWA-SQL注入

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

部署好DVWA后,登陆DVWA首先选择练习的难度等级。DVWA中共分为四种安全级别:Low,Medium,High,Impossible。然后选择练习的模块,这里我们选择SQL Injection(SQL注入)模块。


Low等级

这里写图片描述
选好等级后,进入SQL Injection(SQL注入)模块。
这里写图片描述
首先进行正常操作。输入User ID为1。
这里写图片描述
在尝试输入1’。
这里写图片描述
提示报错,说明存在SQL注入漏洞。接下来我们就要判断SQL语句的POC了。SQL常有三种POC:
(1)….where user_id = $id

(2)….where user_id = ‘$id’

(3)….where user_id = “$id”
首先我们尝试输入1 or 1=1
这里写图片描述
结果和输入1时相同,说明POC不对。
我们在尝试输入1' or '10'='10
这里写图片描述
返回了多个结果,说明POC正确。
我们在看看最后一种输入1" or "10"="10
这里写图片描述
其结果也和输入1时相同。
确定了POC后我们要在确定查询的字段数。使用order by来逐步确定字段数。
首先输入1' order by 1--注意–后面有一个空格!这里字段数肯定大于1,只是为了展示下正确时的结果。
这里写图片描述
我们在输入1' order by 10--
这里写图片描述
这里显示错误说明字段数小于10,我们使用二分法逐步缩小范围,最终确定查询字段数为2。
确定字段数后,我们还要确定字段的顺序。我们输入1' union select 1,2 --
这里写图片描述
说明字段顺序为First name,Surname。
然后我们就要获取我们的数据库了。输入1' union select 1,database() --通过结果可知数据库名为dvwa。
这里写图片描述
我们在获取数据库中的表名。输入1' union select 1,table_name from information_schema.tables where table_schema='dvwa'--通过结果我们得到两个表名guestbook和users。
这里写图片描述
很明显表users中是我们想要得到的信息。我们还要确定表users中的字段名。输入1' union select 1,column_name from information_schema.columns where table_name='users'--
这里写图片描述
其中我们比较想要得到的是用户名和密码,也对应这user和password。我们输入1' union select user,password from users--
这里写图片描述
其中hash密码直接到www.cmd5.com进行cmd5解密即可!


Medium等级

我们修改为Medium等级后发现页面变化很大,没有了原来输入数据的窗口而是换成了下拉单的形式。没有了输入窗口也就意味着Low等级的方法肯定不行了。因此我们只能抓包再进行处理了。
这里写图片描述
抓到数据包后依然是先尝试确定POC。首先将id的参数改为1 or 12=12发现数据包发送成功了,返回了多个值,说明数据库的POC为第一种。
这里写图片描述
我们尝试下1' or '12'='12,响应包显示失败。1" or "12"="12同理也是失败。
这里写图片描述
然后我们要确定字段数等操作和Low等级相同,只不过这里是在OWASP ZAP中进行的而已。
但是当我们修改的id的参数中有单引号’时会报错,可以看出单引号‘被转义了。
这里写图片描述
此时我们可以使用HEX编码将dvwa编码为0x64767761,就可以去掉单引号直接输入了,返回结果也是成功的。
这里写图片描述
这里写图片描述
我们可以查看Medium等级源代码:

<?php 

if( isset( $_POST[ 'Submit' ] ) ) { 
    // Get input 
    $id = $_POST[ 'id' ]; 
    $id = mysql_real_escape_string( $id ); 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    // Get results 
    $num = mysql_numrows( $result ); 
    $i   = 0; 
    while( $i < $num ) { 
        // Display values 
        $first = mysql_result( $result, $i, "first_name" ); 
        $last  = mysql_result( $result, $i, "last_name" ); 

        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 

        // Increase loop count 
        $i++; 
    } 

    //mysql_close(); 
} 

?>

发现Medium级别还有使用mysql_real_escape_string函数对特殊符号进行转义。


High等级

High的等级又有了很大的不同。他会弹出另一个页面,要在弹出的页面上输入数据。
这里写图片描述
那我们还是先按Low等级方法进行尝试,发现High等级与Low等级一模一样。也就是说两者唯一的区别就是,High等级是两个页面操作,而Low等级是一个页面。影响就是High等级使用自动方法sqlmap时会有些复杂。
我们查看High等级的源代码:


<?php 

if( isset( $_SESSION [ 'id' ] ) ) { 
    // Get input 
    $id = $_SESSION[ 'id' ]; 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; 
    $result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' ); 

    // Get results 
    $num = mysql_numrows( $result ); 
    $i   = 0; 
    while( $i < $num ) { 
        // Get values 
        $first = mysql_result( $result, $i, "first_name" ); 
        $last  = mysql_result( $result, $i, "last_name" ); 

        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 

        // Increase loop count 
        $i++; 
    } 

    mysql_close(); 
} 

?> 

High级别的只是在SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。但是虽然添加了LIMIT 1,但是我们可以通过--将其注释掉。


Impossible等级

我们查看源代码:


<?php 

if( isset( $_GET[ 'Submit' ] ) ) { 
    // Check Anti-CSRF token 
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 

    // Get input 
    $id = $_GET[ 'id' ]; 

    // Was a number entered? 
    if(is_numeric( $id )) { 
        // Check the database 
        $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(); 
        $row = $data->fetch(); 

        // Make sure only 1 result is returned 
        if( $data->rowCount() == 1 ) { 
            // Get values 
            $first = $row[ 'first_name' ]; 
            $last  = $row[ 'last_name' ]; 

            // Feedback for end user 
            echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 
        } 
    } 
} 

// Generate Anti-CSRF token 
generateSessionToken(); 

?> 

可以看到,Impossible级别的代码检测了id的数据类型使用预编译绑定id变量,有效防御SQL注入,同时只有返回的查询结果数量为一时,才会成功输出,这样就有效预防了“脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值