在这个级别的CSRF漏洞中,服务端多了一句eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ]校验,ereg()函数是模式匹配,通过超全局数组获取了请求头referer值(也就是访问者向host发起请求时所在的页面)和host值,并且检查host的值是否在referer中出现。根据权威
(https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name),这两个值无法以编程的方式修改,抓包除外,因为在csrf中无法通过抓取客户端的包进行修改,所以按理来说是安全的。实则不然,通过公网服务器,诱使victim访问名字包含host的html文件就可以实现绕过。
(3) High level
- <?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();
-
- ?>
在高级别中的代码,主要是使用了Anti-csrf机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。我们可以按F12来看看这个token:

可以看到不同的用户会返回一个不同的token,这个token在hidden栏里面,这样一来,迫于同源策略,攻击者无法获取victim的token,也就无法实现CSRF攻击。但是真的无法实现吗?配合xss我们还是可以盗取token的,但是这难度无疑增大,我们必须要有服务器的一个xss漏洞来盗取token,然后再使用CSRF。攻击成本也增大。
(4) 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 = mysql_real_escape_string( $pass_curr );
- $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();
-
- ?>
(编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|