3、DVWA——CSRF

一、CSRF概述

  CSRF全称为跨站请求伪造(Cross-site request forgery),是一种网络攻击方式,也被称为 one-click attack 或者 session riding。CSRF攻击利用网站对于用户网页浏览器的信任,挟持用户当前已登陆的Web应用程序,去执行并非用户本意的操作。下图是CSRF的攻击原理:
在这里插入图片描述

  CSRF与XSS的区别:

  • XSS是通过修改页面Javascript等代码后,发给用户从而实现盗取cookie信息,之后利用cookie进行登陆网站等操作。非法操作是黑客。
  • CSRF并没有盗取cookie信息,而是通过用户直接利用cookie进行操作。非法操作并不是黑客,而是用户本身。

二、low

2.1 通关思路

(1)首先,确定我们的用户名和密码分别为:admin和admin。

在这里插入图片描述

(2)按照提示,修改密码,抓取修改密码时浏览器所发的数据包;
在这里插入图片描述
(2)选择Engagement tools,点击CSRF Poc,最后会生成一段payload。

  该payload就是一个特定的网站,一旦用户访问这个网站,该网站就会给原来改密码的服务端发送改密码请求。至于密码改成什么样,完全是由这个伪造的网站决定。

在这里插入图片描述

  得到网站链接:http://burpsuite/show/3/tvpt0va0g5xddv4nytmm71z0p7uhhh2a

在这里插入图片描述

(3)现在可以关闭burp的拦截功能(只是不抓包,但是数据包还是先流向burp),然后在同一个1浏览器访问刚刚伪造的链接。发现密码已被修改!

在这里插入图片描述

刚刚这样操作思路就是参考CSRF的原理:
在这里插入图片描述

2.2 源码分析

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = mysql_real_escape_string( $pass_new ); //转义在 SQL 语句中使用的字符串中的特殊字符(\x00、\n、\r、\、'、"、\x1a)
        $pass_new = md5( $pass_new );  //使用MD5对密码进行加密

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );//mysql_query()查询成功返回True;否则返回False。

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match.</pre>";
    }

    mysql_close();
}

?>

  分析:服务器收到修改密码的请求后,会检查参数password_new与password_conf是否相同,如果相同,就会修改密码,并没有任何的防CSRF机制。

三、medium

3.1 通关思路

(1)首先,确定我们的用户名和密码分别为:admin和admin。

在这里插入图片描述
(2)同样,使用插件生成CSRF POC。
在这里插入图片描述

(3)在同一个浏览器上访问生成的链接,抓包,修改renferer值为http://192.168.92.1:32769/vulnerabilities/csrf/
在这里插入图片描述
(4)重新登陆,发现密码已被修改。

在这里插入图片描述

  注:这里绕过referer值是通过burp,实际情况下,被害者点击链接后,按照以上方法,攻击方是抓不到被害者的数据包的。还可以在伪造的服务端重新设置referer值来绕过referer检测。

3.2 源码分析

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
    //eregi():在一个字符串搜索指定的模式的字符串。
    //$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。
    //$_SERVER['SERVER_NAME'] :服务器主机的名称。
    //$_SERVER['HTTP_REFERER'] :链接到当前页面的前一页面的 URL 地址
    if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) {
        // Get input
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];

        // Do the passwords match?
        if( $pass_new == $pass_conf ) {
            // They do!
            $pass_new = mysql_real_escape_string( $pass_new );
            $pass_new = md5( $pass_new );

            // Update the database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );

            // Feedback for the user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            echo "<pre>Passwords did not match.</pre>";
        }
    }
    else {
        // Didn't come from a trusted source
        echo "<pre>That request didn't look correct.</pre>";
    }

    mysql_close();
}

?> 

  分析:代码检查了保留变量HTTP_REFERER (http包头部的Referer字段的值,表示来源地址)是否包含SERVER_NAME(http包头部的 Host 字段表示要访问的主机名)。针对这一过滤规则,我们只要想办法绕过,那么我们后面的代码和low级别的基本都一样了,很容易实现CSRF攻击。

四、high

4.1 通关思路

  使用CSRF Token Tracker插件,来捕获每次服务端返回的token。

在这里插入图片描述

4.2 源码分析

<?php

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

    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = mysql_real_escape_string( $pass_new );
        $pass_new = md5( $pass_new );

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match.</pre>";
    }

    mysql_close();
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

  分析:High级别的代码增加了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端请求。

五、impossible

<?php

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

    // Get input
    $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 );  //转义一下字符`\x00、\n、\r、\、'、"、\x1a`
    $pass_curr = md5( $pass_curr );

    // Check that the current password is correct
    $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
    $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
    $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
    $data->execute();

    // Do both new passwords match and does the current password match the user?
    if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
        // It does!
        $pass_new = stripslashes( $pass_new );
        $pass_new = mysql_real_escape_string( $pass_new );
        $pass_new = md5( $pass_new );

        // Update database with new password
        $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
        $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
        $data->execute();

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match or current password incorrect.</pre>";
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

  分析

  • 要求先输入密码再修改,攻击者不知道原始密码的情况下是无法发起 CSRF 攻击的。
  • 加入了随机token;
  • 使用PDO进行SQL语句查询,避免直接将用户的传参拼接到SQL语句,防止SQL注入。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值