安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御

安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御

本篇继续对于安全性测试话题,结合DVWA进行研习。

CSRF(Cross-site request forgery):跨站请求伪造

1. 跨站请求伪造攻击

CSRF则通过伪装成受信任用户的请求来利用受信任的网站,诱使用户使用攻击性网站,从而达到直接劫持用户会话的目的。

由于现在的主流浏览器比如火狐和谷歌,都倾向于使用单个进程来管理用户会话(比如我们在FF和Chrome中,当要访问一个新页面时,通常是通过新增浏览器页面来达到的,而不是新开一个浏览器客户端进程),所以攻击者就可以通过用户新开的页面来劫持用户的已有cookie等关键信息。
常见的攻击形式,是通过邮件,QQ等即时聊天工具,给被攻击对象发送伪造链接。被攻击者一旦访问了该恶意链接,攻击即生效。

DVWA的相应模块中,使用一个密码修改功能来展示了CSRF攻击的可能性。

构造攻击

我们观察上述密码修改功能所触发的请求:

可以看到这个请求非常之简单,所需传递的只有三个参数

  • password_new
  • password_conf
  • change

那么如果攻击者直接构造这样一条请求交给被攻击者去执行会怎么样?
比如我构造这样一条URL:

如果被攻击者傻呵呵的点击了,那么恭喜他,他的密码就已经被我改成"attackerpw"了。
当然了,这个链接的攻击意图过于明显了,攻击者还可以通过伪装一下这个链接,从而达到神不知鬼不觉的目的。

  • 比如通过缩短链接服务:

  • 比如通过构建一个带有攻击代码的页面,诱使被攻击者访问:

上图看起来就是个不明所以的网页?但实际上访问到网页的时候红框部分的攻击代码就已经生效了!

2.CSRF的防御

下面我们看一看DVWA是如何防御跨站脚本伪造的:
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
            $html .= "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            $html .= "<pre>Passwords did not match.</pre>";
        }
    }
    else {
        // Didn‘t come from a trusted source
        $html .= "<pre>That request didn‘t look correct.</pre>";
    }

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

?>

可以看到中级防御机制,关键在于以下部分:

即判断请求来源,如果类似修改密码的这种请求来自于未知第三方地址,那么则不执行修改逻辑。
这是不难绕过的,只需在攻击页面中加入HTTP_REFERER并使其与被攻击server一致即可。

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
        $html .= "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        $html .= "<pre>Passwords did not match.</pre>";
    }

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

// Generate Anti-CSRF token
generateSessionToken();

?>

嘞了嘞了,耳熟能详的Token他来了:

用户每次访问页面,服务器会随机生成一个Token,相当于用户的身份牌。只有身份牌验证通过,功能逻辑才执行。
Token是现在很流行的令牌机制,但是他也是一种比较简单的机制,绝非无懈可击。接口测试做的多的话应该能感受到,我们接口测试中经常会对Token做传递处理。
实际token就在网页元素里面,如下图所示

我们通过抓包、爬虫、元素定位等方式完全可以获取到,传递到攻击页面中 - 当然这会需要一定的代码编写量了!

Impossible级别

DVWA提供的最高级别防御机制,说穿了非常简单,即修改密码前,强制要求用户输入旧密码。
如果不知道旧密码,则无论怎样也无法修改用户密码。

3. CSRF防御能力测试

结合着上述讨论,同样我们可以总结一下这一安全测试点的测试思路。

对于CSRF跨站脚本伪造攻击我们可以做:

  • 渗透性测试: 扮演攻击者的角色,利用已知的攻击手段尝试跨站脚本伪造,比如自己构造请求和简单的页面进行攻击。
  • 运行时测试: 实际就是功能测试,我们可以通过验证系统是否存在相应的防御功能:比如token机制,请求来源验证等。
  • 代码审计: 了解了CSRF的几个级别的防御机制,那么就可以通过代码审计的方式来确定被测应用的后台逻辑有无相应防御机制。

还有一个问题在于,什么样的系统功能点可能是CSRF攻击的敏感区域呢?

从本文的例子中我们可以看到,当系统以一种简单的请求方式实现某种功能时,CSRF就存在劫持用户会话的可能性。那么这就要求测试人员能够敏锐的发现类似的系统特性区域,并且予以判断,是否有可能被会话劫持。

比如在一个购物平台中,订单的提交流程如果过于简单,一个简单的get请求就能实现下单功能(从这一点来说,get请求就不应用于处理敏感操作,发现这种情况就是你测试的点!),那么你就可以摩拳擦掌,考虑来一次渗透测试了。

从这个角度来说,对于安全性测试,知识和技术的累积是一方面,而敏锐的思维能力特别是逆向思维能力更加重要!

原文地址:https://www.cnblogs.com/ht22ht22/p/11660640.html

时间: 2024-09-30 04:10:38

安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御的相关文章

CSRF(跨站请求伪造攻击)漏洞详解

Cross-Site Request Forgery(CSRF),中文一般译作跨站点 请求伪造.经常入选owasp漏洞列表Top10,在当前web漏洞排行中,与XSS和SQL注入并列前三.与前两者相比,CSRF相对来说受到的关注要小很多,但是危害却非常大. 通常情况下,有三种方法被广泛用来防御CSRF攻击:验证token,验证HTTP请求的Referer,还有验证XMLHttpRequests里的自定义header.鉴于种种原因,这三种方法都不是那么完美,各有利弊. 二 CSRF的分类 在跨站请

CSRF(跨站请求伪造)攻击方式

一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF. 二.CSRF可以做什么? 你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求.CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全. 三.CSRF漏洞现状 CSRF这

Python Django 生命周期 中间键 csrf跨站请求伪造 auth认证模块 settings功能插拔式源码

一 django 生命周期 二 django中间键 1.什么是中间键 官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定的功能. 简单来说就相当于django门户,保安:它本质上就是一个自定义类,类中定义了几个方法. 请求的时候需要先经过中间件才能到达django后端(urls,views,templates,models): 响应走的时候也需要经过中间件才能到达w

CSRF(跨站请求伪造攻击)详解以及防护之道

CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作,有很大的危害性.然而,该攻击方式并不为大家所熟知,很多网站都有 CSRF 的安全漏洞.本文首先介绍 CSRF 的基本原理与其危害性,然后就目前常用的几种防御方法进行分析,比较其优劣.最后,本文将以实例展示如何在网站中防御 CSRF 的攻击,并分享一些开发过程中的最佳实践. C

Ajax--参数,csrf跨站请求伪造,serialize(),上传文件formdata

https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js. 一:参数,processData,contentType,traditional,dataType ######################------------data---------################ data: 当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式 (urlencoded:?a=

Django框架 之 基于Ajax中csrf跨站请求伪造

ajax中csrf跨站请求伪造 方式一 1 2 3 $.ajaxSetup({     data: {csrfmiddlewaretoken: '{{ csrf_token }}' }, }); 方式二 1 2 3 4 5 <form> {% csrf_token %} </form><br><br><br>$.ajax({<br>...<br>data:{ "csrfmiddlewaretoken":

Django框架(十六)-- 中间件、CSRF跨站请求伪造

一.什么是中间件 中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出 二.中间件的作用 如果你想修改请求,例如被传送到view中的HttpRequest对象. 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现. 可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现. Django默认的中间件:(在django项目的settings模块中,有一个 MIDDLE

☆Django☆---中间件 csrf跨站请求伪造 auth模块 settings功能插拔式源码

Django中间件 django生命周期图 中间件: 概念: Django中间件就类似于 django的保安   请求 的时候需要先经过中间件才能到达django后端(urls, views)   响应 走的时候也需要经过中间件才能到达web服务网关接口 django默认的七个中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.Session

Django中间件、csrf跨站请求伪造以及基于Django中间件思想实现功能的插拔式配置

一.django中间件 1.1解释:django中间件是类似于是django的保安,请求的时候需要先经过中间件才能到达django后端(urls,views,templates,models),响应走的时候也需要经过中间件才能到达web服务网关接口 1.2django默认的七个中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.Session