3、DVWA——CSRF

文章目录

  • 一、CSRF概述
  • 二、low
    • 2.1 通关思路
    • 2.2 源码分析
  • 三、medium
    • 3.1 通关思路
    • 3.2 源码分析
  • 四、high
    • 4.1 通关思路
    • 4.2 源码分析
  • 五、impossible

一、CSRF概述

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

  CSRF与XSS的区别:

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

二、low

2.1 通关思路

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

3、DVWA——CSRF_第2张图片

(2)按照提示,修改密码,抓取修改密码时浏览器所发的数据包;
3、DVWA——CSRF_第3张图片
(2)选择Engagement tools,点击CSRF Poc,最后会生成一段payload。

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

3、DVWA——CSRF_第4张图片

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

3、DVWA——CSRF_第5张图片

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

3、DVWA——CSRF_第6张图片

刚刚这样操作思路就是参考CSRF的原理:
3、DVWA——CSRF_第7张图片

2.2 源码分析



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( '
' . mysql_error() . '
'
);//mysql_query()查询成功返回True;否则返回False。 // Feedback for the user echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match.
"
; } mysql_close(); } ?>

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

三、medium

3.1 通关思路

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

3、DVWA——CSRF_第8张图片
(2)同样,使用插件生成CSRF POC。
3、DVWA——CSRF_第9张图片

(3)在同一个浏览器上访问生成的链接,抓包,修改renferer值为http://192.168.92.1:32769/vulnerabilities/csrf/
3、DVWA——CSRF_第10张图片
(4)重新登陆,发现密码已被修改。

3、DVWA——CSRF_第11张图片

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

3.2 源码分析



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( '
' . mysql_error() . '
'
); // Feedback for the user echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match.
"
; } } else { // Didn't come from a trusted source echo "
That request didn't look correct.
"
; } mysql_close(); } ?>

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

四、high

4.1 通关思路

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

3、DVWA——CSRF_第12张图片

4.2 源码分析



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( '
' . mysql_error() . '
'
); // Feedback for the user echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match.
"
; } mysql_close(); } // Generate Anti-CSRF token generateSessionToken(); ?>

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

五、impossible



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 "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match or current password incorrect.
"
; } } // Generate Anti-CSRF token generateSessionToken(); ?>

  分析

  • 要求先输入密码再修改,攻击者不知道原始密码的情况下是无法发起 CSRF 攻击的。
  • 加入了随机token;
  • 使用PDO进行SQL语句查询,避免直接将用户的传参拼接到SQL语句,防止SQL注入。

你可能感兴趣的:(DVWA,安全,csrf)