当前位置: 首页 > article >正文

DVWA靶场第三关 CSRF

CSRF的中文叫:”跨站请求攻击“,它是通过仿照某一个特殊的网页(重置密码)来进行诱惑性攻击。

难度(low级)

在这里插入图片描述

审计代码:

 <?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 = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new = md5( $pass_new );

        // Update the database
        $current_user = dvwaCurrentUser();
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . $current_user . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

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

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

G L O B A L S :引用全局作用域中可用的全部变量。 GLOBALS :引用全局作用域中可用的全部变量。 GLOBALS:引用全局作用域中可用的全部变量。GLOBALS 这种全局变量用于在 PHP 脚本中的任意位置访问全局变量(从函数或方法中均可)。PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。变量的名字就是数组的键。

从源代码可以看出这里只是对用户输入的两个密码进行判断,看是否相等。不相等就提示密码不匹配。

相等的话,查看有没有设置数据库连接的全局变量和其是否为一个对象。如果是的话,用mysqli_real_escape_string()函数去转义一些字符,如果不是的话输出错误。

是同一个对象的话,再用md5进行加密,再更新数据库。

知道了这些之后,我们第一次尝试两次密码不一致看看。

两次密码不一致则提示,密码不一致不允许修改,并且我们在链接上可以看到修改的明文密码,那我们思考一个问题能不能用这个链接直接改密码呢?
在这里插入图片描述

密码链接:
http://172.31.63.146/DVWA/vulnerabilities/csrf/?
漏洞利用:

我们打开另一个页面,在顶部URL中自己输入如下的payload。
password_new=123456&password_conf=789456&Change=Change#
在浏览器中点开链接,提示密码修改成功。

在这里插入图片描述

低难度则证明咱们可以利用这个链接任意的修改密码了,实质上这里就存在csrf漏洞我们伪造了修改密码的链接,从而实现了任意密码修改。

难度(Medium)

审计代码

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
        // 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 = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );

            // Update the database
            $current_user = dvwaCurrentUser();
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . $current_user . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</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>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

Medium类型的代码在Low级别的基础上,加上了对用户请求头的中的Referer字段进行验证。

if( stripos( S E R V E R [ ′ H T T P R E F E R E R ′ ] , _SERVER[ 'HTTP_REFERER' ] , SERVER[HTTPREFERER],_SERVER[ ‘SERVER_NAME’ ]) !== false )

即用户的请求头中的Referer字段必须包含了服务器的名字。关于Http Referer字段。

当我们再打开另一个页面,在顶部URL中自己输入如下的时,http://172.31.63.146/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change

它会报错,提示你:That request didn’t look correct。
在这里插入图片描述

我们使用burpsuite抓包分析一下:

在界面上可以修改成功,Referer字段限制从从哪里访问的来源。
Referer: http://172.31.63.146/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change
提示修改成功:

password changed
在这里插入图片描述

我们任意浏览器打开链接没有Referer字段则显示修改失败:

That request didn’t look correct。
在这里插入图片描述

漏洞利用:

那么我思考一下在这个数据包上面伪造一个Referer头能不能利用成功呢?

把上述数据包发送到Repeater上加入。

Referer: http://172.20.10.2/dvwa/vulnerabilities/csrf/

提示密码修改成功,这表示我们能够通过伪造Referer头来实现跨站请求伪造,达到我们修改密码的目的。
在这里插入图片描述

难度(High)

源码解析

<?php

$change = false;
$request_type = "html";
$return_message = "Request Failed";

if ($_SERVER['REQUEST_METHOD'] == "POST" && array_key_exists ("CONTENT_TYPE", $_SERVER) && $_SERVER['CONTENT_TYPE'] == "application/json") {
    $data = json_decode(file_get_contents('php://input'), true);
    $request_type = "json";
    if (array_key_exists("HTTP_USER_TOKEN", $_SERVER) &&
        array_key_exists("password_new", $data) &&
        array_key_exists("password_conf", $data) &&
        array_key_exists("Change", $data)) {
        $token = $_SERVER['HTTP_USER_TOKEN'];
        $pass_new = $data["password_new"];
        $pass_conf = $data["password_conf"];
        $change = true;
    }
} else {
    if (array_key_exists("user_token", $_REQUEST) &&
        array_key_exists("password_new", $_REQUEST) &&
        array_key_exists("password_conf", $_REQUEST) &&
        array_key_exists("Change", $_REQUEST)) {
        $token = $_REQUEST["user_token"];
        $pass_new = $_REQUEST["password_new"];
        $pass_conf = $_REQUEST["password_conf"];
        $change = true;
    }
}

if ($change) {
    // Check Anti-CSRF token
    checkToken( $token, $_SESSION[ 'session_token' ], 'index.php' );

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = mysqli_real_escape_string ($GLOBALS["___mysqli_ston"], $pass_new);
        $pass_new = md5( $pass_new );

        // Update the database
        $current_user = dvwaCurrentUser();
        $insert = "UPDATE `users` SET password = '" . $pass_new . "' WHERE user = '" . $current_user . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert );

        // Feedback for the user
        $return_message = "Password Changed.";
    }
    else {
        // Issue with passwords matching
        $return_message = "Passwords did not match.";
    }

    mysqli_close($GLOBALS["___mysqli_ston"]);

    if ($request_type == "json") {
        generateSessionToken();
 

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

因为该请求是get请求,所以token验证会被放在请求URL中,我们随便输入密码验证一下,可以看到,在请求的URL中最末尾加入了token。
http://172.31.63.146/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change&user_token=86c02ef72eb549a0f63d81d9e19784b2#

漏洞利用:

要绕过High级别的反CSRF机制,关键是要获取token,要利用受害者的cookie,去修改密码的页面,获取关键的token。

可以利用High级别的XSS漏洞协助获取Anti-CSRF token。

XSS注入有长度限制,不能够注入完整的攻击脚本,所以只获取Anti-CSRF token即可。

在XSS中使用以下payload获取Token。

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/958dce270014441f93a4731eb7fd0ddb.png) 将Token复制到修改密码的数据包中发现,完成修改。 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7c439b579abc4932a5120b2c9e7d419d.png)

最后尝试登录一次成功
在这里插入图片描述
在这里插入图片描述

难度(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 = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $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;' );
    $current_user = dvwaCurrentUser();
    $data->bindParam( ':user', $current_user, 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 = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $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 );
        $current_user = dvwaCurrentUser();
        $data->bindParam( ':user', $current_user, 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 攻击的。


http://www.kler.cn/a/452269.html

相关文章:

  • Java 中 getClass() 方法的使用与原理分析:深入理解对象类型信息
  • git push origin HEAD:refs/for/分支名
  • VMware虚拟机超详细安装Linux教程(最新版)
  • 关于Edge浏览器的设置
  • 傅里叶变换原理
  • 大数据-256 离线数仓 - Atlas 数据仓库元数据管理 正式安装 启动服务访问 Hive血缘关系导入
  • 【jvm】内存泄漏与内存溢出的区别
  • [Python3] Sanic中间件
  • 你比AI更有价值吗?
  • 微信小程序-基于Vant Weapp UI 组件库的Area 省市区选择
  • ESLint (10)
  • 低空经济的地理信息支撑:构建安全、高效的飞行管理体系
  • CSS|15 CSS3结构伪类border-collapse伪元素
  • PHP 微信棋牌开发全解析:高级教程
  • 解决Ascend上vllm运行时出现urllib3.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]
  • redis和mysql的区别
  • 威尔克斯(Wilks)分布
  • 基于Pycharm与数据库的新闻管理系统(3)MongoDB
  • shell拓展知识
  • React State(状态)
  • Qt实现Android的图案密码(图形解锁)源码分享
  • 计算机的错误计算(一百九十一)
  • 信息抽取(NLP)是什么技术有哪些应用?
  • 大数据-256 离线数仓 - Atlas 数据仓库元数据管理 正式安装 启动服务访问 Hive血缘关系导入
  • 《Web 搜索引擎优化》
  • CI/CD在前端项目的应用:实现自动化与持续交付