DVWA之CSRF跨站请求伪造

CSRF(Cross Site Request Forgery)跨域请求伪造

有些像XSS(跨站脚本),但是跟XSS有很多不同。具体区别可以参考freebuf中的文章:

漏洞科普:对于XSS和CSRF你究竟了解多少

csrf_01

查看网页源代码,找到关键代码部分:


<form action="#" method="GET">
    Current password:<br>
    <input type="password" AUTOCOMPLETE="off" name="password_current"><br>
    New password:<br>
    <input type="password" AUTOCOMPLETE="off" name="password_new"><br>
    Confirm new password: <br>
    <input type="password" AUTOCOMPLETE="off" name="password_conf"><br>
    <input type="submit" value="Change" name="Change">
</form>

输入密码修改,得到一个链接:

http://127.0.0.1/DVWA-1.0.8/vulnerabilities/csrf/?password_current=aaa&password_new=bbb&password_conf=bbb&Change=Change#

此处,我们在文本框中依次填入 aaa bbb bbb,点击 Change 按钮后提示 Password Changed

表名密码修改成功。

CSRF的关键用法不会让用户去填这样一个表单,而是通过上边生成的链接,直接发送给受害用户,当用户点击之后,密码就自动修改为攻击者构造的密码。

通过查看不同安全等级源代码,分析CSRF的漏洞原理

(1)Low Security Level

<?php 
    //Low Security Level             
    if (isset($_GET['Change'])) { 
     
        // Turn requests into variables 
        $pass_new = $_GET['password_new']; 
        $pass_conf = $_GET['password_conf']; 


        if (($pass_new == $pass_conf)){ 
            $pass_new = mysql_real_escape_string($pass_new); 
            $pass_new = md5($pass_new); 

            $insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';"; 
            $result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' ); 
                         
            echo "<pre> Password Changed </pre>";         
            mysql_close(); 
        } 
     
        else{         
            echo "<pre> Passwords did not match. </pre>";             
        } 

    } 
?>

(2)Medium Security Level

<?php 
    //Medium Security Level         
    if (isset($_GET['Change'])) { 
     
        // Checks the http referer header 
        if ( eregi ( "127.0.0.1", $_SERVER['HTTP_REFERER'] ) ){ 
     
            // Turn requests into variables 
            $pass_new = $_GET['password_new']; 
            $pass_conf = $_GET['password_conf']; 

            if ($pass_new == $pass_conf){ 
                $pass_new = mysql_real_escape_string($pass_new); 
                $pass_new = md5($pass_new); 

                $insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';"; 
                $result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' ); 
                         
                echo "<pre> Password Changed </pre>";         
                mysql_close(); 
            } 
     
            else{         
                echo "<pre> Passwords did not match. </pre>";             
            }     

        } 
         
    } 
?>

(3)High Security Level

<?php 
    //High Security Level         
    if (isset($_GET['Change'])) { 
     
        // Turn requests into variables 
        $pass_curr = $_GET['password_current']; 
        $pass_new = $_GET['password_new']; 
        $pass_conf = $_GET['password_conf']; 

        // Sanitise current password input 
        $pass_curr = stripslashes( $pass_curr ); 
        $pass_curr = mysql_real_escape_string( $pass_curr ); 
        $pass_curr = md5( $pass_curr ); 
         
        // Check that the current password is correct 
        $qry = "SELECT password FROM `users` WHERE user='admin' AND password='$pass_curr';"; 
        $result = mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' ); 

        if (($pass_new == $pass_conf) && ( $result && mysql_num_rows( $result ) == 1 )){ 
            $pass_new = mysql_real_escape_string($pass_new); 
            $pass_new = md5($pass_new); 

            $insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';"; 
            $result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' ); 
                         
            echo "<pre> Password Changed </pre>";         
            mysql_close(); 
        } 
     
        else{         
            echo "<pre> Passwords did not match or current password incorrect. </pre>";             
        } 

    } 
?>

对比这三种不同安全等级的源代码发现:

(1)Low Level:不需要验证当前密码,只需要输入新密码和确认新密码,相等时就可以更改密码。毫无安全性可言

(2)Medium Level:验证HTTP_REFERER是否是127.0.0.1,判断请求的来源是否是本机,可以通过Burp Suite抓包,然后修改Reffer的值,只要包含127.0.0.1就可以实现修改,甚至可以只是127.0.0.1这个值

(3)High Level: 首先对输入的当前密码进行去下划线以及转义,md5加密操作,避免了可能存在的注入语句,然后在数据库中查找当前用户(admin)对应的密码是否是输入的密码,如果正确说明存在这个用户,输入的当前密码是对的。然后通过比较新输入密码和确认新密码相同,就可以进行密码修改操作。这个等级下的难度主要是要知道当前密码。这也是密码修改的必须流程。

CSRF防御思路:

(1)就本例而言,防止密码修改首先应当验证当前密码

(2)对请求的来源进行判定,即 HTTP_REFERER

(3)在请求中加入tokens等验证信息,防止被攻击者窃取

 

 

您可能还喜欢...