DVWA-CSRF(跨站请求伪造)

DVWA-CSRF(跨站请求伪造)

介绍:

CSRF,全称Cross-site request forgery,翻译过来就是跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。

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
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $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);
}

?>

我们打开csrf页面,可以看到是一个改密的页面,当我们提交改密的请求时,可以看到浏览器发出了一个get请求,这个请求就是需要我们构造的请求。其中password_new和password_conf就是我们想要修改后的密码。

在这里插入图片描述

现在我们想一下怎么来利用这个漏洞,这个漏洞的利用就是:

目标用户在登陆了目标网站的情况下,访问了我们构造的恶意改密链接。访问了我们的改密链接过后,由于它带着目标网站的cookie,所以我们的而已请求可以被服务器认识,那么攻击也就成功了。

我们重新打开一个页面,将密码改为123456,重新运行
http://192.168.5.5/dvwa/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#

我们来登录一下,发现密码123登录不上去,123456可以登录上去。

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
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $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);
}

?> 

同样是get方式来更改密码,拿到可以构造的url:

然后我们再其它复制这个链接,新开一个窗口请求一下,看看能否成功:

很明显,改密失败了,而且还报了一个错误,从这个错误可以推断出后台进行了http_referer判断,这个我们有机会绕过的,我们从源码里看一下到底http_referrer需要满足怎样的要求:

关键在这一句:

$_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false

就是http_referer中必须有被请求页面的主机名,那么就很简单了,我就直接构造一个文件名为localhost.html(的页面放在我的服务器上,然后里面还是写一个改密请求:
<img src="http://192.168.5.5/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change">

这样后台在验证referer的时候,也就有它的主机名了,也就是我这里的localhost,这样就成功绕过了检验。

high

<?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 = ((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
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $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);
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

可以看到,High级别的代码加入了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。所以,我们现在想要构造一个恶意链接必须要拿到这个东西。怎么拿到这个东西呢?现在有两个思路:

A. 仅仅利用csrf,构造一个恶意链接,这个链接指向我们服务器的某一个页面,这个页面中用iframe包含了这个登陆页面,并通过js脚本将user_token给取出来,然后在构造链接,并自动访问。

B. 利用xss,xss去获取user_token,然后再构造链接

A方案看似很完美,但是自从有了同源策略这个东西,同源策略禁止了跨域的读,这里跨域就是从我的服务器读取受害者的域里的东西。

B方案就是直接利用dvwa的xss平台,插入一段改密脚本:

<iframe src="../csrf" "var a=new XMLHttpRequest();var token=top.frames[0].document.getElementsByName('user_token')[0].value;a.open('get','../csrf/index.php?password_new=1234&password_conf=1234&Change=Change&user_token='+token,false);a.send(null)">

脚本大体思路:

1.嵌入目标页面

2.获取token

3.利用获取到的token构造恶意链接

4.利用xhr技术,将恶意请求自动发送
在这里插入图片描述
注:这里有一处用了html编码,是对字母i进行了编码,如果不变码的话,会被过滤器给过滤掉

猜你喜欢

转载自blog.csdn.net/qq_42636435/article/details/88747704