DVWA之CSRF

CSRF:跨站点请求伪造(Cross—Site Request Forgery)
也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种冒充合法用户在当前登录或登录过的且登录信息尚未过期的Web浏览器或者应用程序上执行恶意的操作的攻击方法。跟跨站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

漏洞原理:

合法路人甲登录网站A,登录成功后,服务器返回一个存有用户登录信息的cookie存储在浏览器中,然后未退出网站A,又打开 了一个标签页访问网站B,而网站B接收到合法路人甲请求,而网站B存在一个恶意代码返回给路人甲要请求访问网站A,而网站A认为该恶意请求是合法路人甲发出的,所以会以路人甲的cookie信息处理该请求,导致了恶意代码的执行。

可以看出,攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义执行操作

与XSS的区别:
CSRF攻击是需要用户登录,hacker冒充合法用户发送恶意请求

XSS攻击是,hacker在站点嵌入恶意代码并且存储在数据库中,合法用户访问该站点时将自身cookie发送给hacker,hacker利用该cookie来执行操作

low level

分析代码:

mysqli_real_escape_string()函数时用来防止SQL注入的

代码没有验证,直接利用BP完成:
在这里插入图片描述
可以看到是通过GET请求的:

?password_new=password&password_conf=password&Change=Change

构造payload:

http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change 

但是这样的url一眼就能识破是个陷阱,因此需要改变一下:

这里说明下,如果用localhost是无法转换的,可以应用127.0.0.1

在这里插入图片描述

网址:http://www.8cc7.com/

生成:
在这里插入图片描述

这样就不会有人起疑心啦~

所以这里有必要提醒一句啦:
见到这种短的,不常见的网址,不要因为好奇去点哦 😃

访问一下试试:
在这里插入图片描述
这样密码就修改了…

但是链接会弹到修改密码界面,这样的手法也并不高明,很容易看出来修改了密码

这里可以写一个简单的HTML页面:

<img src="http://r6d.cn/bm317" border="0" style="display:none;"/>
<h1>404</h1>
<h2>file not found.</h2>

在这里插入图片描述
这样有一定的隐蔽性~

medium level

分析源码:

stripos() :函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
$_SERVER['HTTP_REFERER'] :链接到当前页面的前一页面的 URL 地址。
$_SERVER[ 'SERVER_NAME' ]:服务器主机名称

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

这一句检查了服务器主机名称,直接像low level那样会报错:
在这里插入图片描述
我们首先正常访问,然后用BP抓包:
在这里插入图片描述
然后直接输入url访问,用BP抓包:

http://localhost/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change

在这里插入图片描述
这里发现没有Referer字段,可以自己添加一个,将正常访问时的Referer加上试试:

在这里插入图片描述
成功:
在这里插入图片描述
这里只要含有主机名即可,无需完整的路径。

high level

代码分析:

checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

这里加入了令牌校验技术,每次在刷新页面时都会检验一个随机产生的token,只有token验证成功才会执行请求。

使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
1、客户端使用用户名和密码请求登录
2、服务端收到请求去验证用户名与密码
3、验证成功后,服务端会像客户端发一个Token
4、客户端收到Token以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
5、 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token 服务端收到请求
6、然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据

这种防御机制明显比起上边两种更安全一些,但是还是存在一定的漏洞可以利用,而本次使用的是GET请求,token会出现在url里:

?password_new=password&password_conf=password&Change=Change&user_token=2758ee93c16690f79b2d1402bf3f5b2a#

我们但是可以得到服务端的token值便可以构造payload

这里只是知道大概的原理,还不会具体操作,这个只能以失败告终了~~

想到一种可能,可以利用存储XSS,只要点击了页面便可以获取到token…

小白能力有限,期待大佬可以教教俺 [/鞠躬拜谢]

impossible level

代码分析:

<?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;' );
    $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 = ((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 );
        $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();

?>

这里除了令牌验证,还加入了PDO预定义常量,几乎杜绝了CSRF攻击

·
·
·
·
·
·
<小白初试,大佬多多指正>

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值