CSRF攻击(简介、原理及实例、分类、检测、防范方法)

CSRF攻击

CSRF是Web应用程序的一种常见漏洞,其攻击特性是危害性大但非常隐蔽,尤其是在大量Web 2.0技术的应用背景下,攻击者完全可以在用户毫无察觉的情况下发起CSRF攻击。本文将对其基本特性、攻击原理、攻击分类、检测方法及防范手段做一个系统的阐述,并列举攻击实例。

1、CSRF漏洞简介  

      Cross-site request forgery 简称为“CSRF”,在CSRF的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了。所以CSRF攻击也成为"one click"攻击。

2、CSRF攻击原理及实例

      这非常好理解,就像我们登陆网上银行后,Web浏览器已经跟可信的站点建立了一个经认证的会话。之后,只要是通过该Web浏览器这个认证的会话所发送的请求,都被视为可信的动作,例如转账,汇款等操作。当我们在一段时间内不进行操作后,在来重新做转账,或者汇款操作,那么这个站点可能会提示你:您的身份已过期,请重新登陆或者会话结束等消息。

       而CSRF攻击则是建立会话之上的攻击。比如当你登陆了网上银行,正在进行转账业务,这时你的某个QQ好友(攻击者)发来一条消息(URL),这条消息是攻击者精心构造的转账业务代码。而且与你所登录的网站是同一个银行,你可能认为这个网站是安全的,并不是什么钓鱼网站之类的,然后打开了这条URL,那么你的账户的钱可能就在你的这一次小小点击上全部丢失。

        主要是因为你的浏览器正处于与此网站的会话之中,那么一些操作都是合法的,而入侵者构造的这段代码只不过是正常的转账操作代码而已。

比如说你想给用户spisec转账1000元,那么点击提交按钮之后,可能会发送以下请求:

http://www.xxx.com/pay.jsp?user=spisec&money=1000

而攻击者仅仅是改变一下user参数与money参数即可完成一次“合法”的攻击,如:

http://www.xxx.com/pay.jsp?user=hack&money=10000

      当你访问了这条URL之后,就会自动向hack这个账户里面转入10000元。而这是你亲手造成的,并没因为有人去破解你的密码或者是Web服务器被入侵所导致的你的金钱丢失。下面以CSRF攻击原理图给大家形象总结:

1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

通过以上的攻击原理描述个人总结CSRF两个侧重点:

1、CSRF的攻击建立在浏览器与Web服务器的会话之中。

2、欺骗用户访问URL


3、CSRF攻击分类

 CSRF漏洞一般分为站外站内两种类型。

      CSRF站外类型的漏洞本质上就是传统意义上的外部提交数据问题。通常程序员会考虑给一些留言或者评论的表单加上水印以防止SPAM问题(这里,SPAM可以简单的理解为垃圾留言、垃圾评论,或者是带有站外链接的恶意回复),但是有时为了提高用户的体验性,可能没有对一些操作做任何限制,所以攻击者可以事先预测并设置请求的参数,在站外的Web页面里编写脚本伪造文件请求,或者和自动提交的表单一起使用来实现GET、POST请求,当用户在会话状态下点击链接访问站外Web页面,客户端就被强迫发起请求。

      CSRF站内类型的漏洞在一定程度上是由于程序员滥用$_REQUEST类变量造成的。在一些敏感的操作中(如修改密码、添加用户等),本来要求用户从表单提交发起POST请求传递参数给程序,但是由于使用了$_REQUEST等变量,程序除支持接收POST请求传递的参数外也支持接收GET请求传递的参数,这样就会为攻击者使用CSRF攻击创造条件。一般攻击者只要把预测的请求参数放在站内一个贴子或者留言的图片链接里,受害者浏览了这样的页面就会被强迫发起这些请求。

4、CSRF 漏洞检测

      检测CSRF漏洞是一项比较繁琐的工作,最简单的方法就是抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。

       随着对CSRF漏洞研究的不断深入,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。以CSRFTester工具为例,CSRF漏洞检测工具的测试原理如下:使用CSRFTester进行测试时,首先需要抓取我们在浏览器中访问过的所有链接以及所有的表单等信息,然后通过在CSRFTester中修改相应的表单等信息,重新提交,这相当于一次伪造客户端请求。如果修改后的测试请求成功被网站服务器接受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。   Burp Suite也能实现此功能。

5、如何挖掘Csrf漏洞

  • 扫描器

  • 修改密码的地方

  • 添加用户的地方

  • 数据库备份的地方

  • 数据交易、支付等

  • 等其它一些对话框钓鱼页面

  • CSRF一般与XSS结合使用

步骤:

打开dz论坛靶场环境

http://10.0.0.101:90/dz/upload/forum.php

 登录dz后点击管理中心:

 新建用户:(新手上路:最低权限)

用户名:
test
密 码:
123456
Email:
1111111111@gq.com

添加论坛模块:

 点击站长查看UCenter 访问地址是否正确:

点击 UCenter进行登录:

 

  UCenter数据备份处有CSRF漏洞:

 后台提交备份就会在服务器主机根目录下dz\upload\uc_server\data\backup\目录下生成备份文件夹里有备份文件:(dz为开源)

C:\phpStudy\WWW\dz\upload\uc_server\data\backup\backup_240517_wKXQfP

生成的 backup_240517_wKXQfP文件夹下的备份文件:240517_YpISnQ-1.sql

 

重新通过bp抓包只能获取到备份生成的文件夹名,文件名获取不到:

用bp把请求行生成的文件夹 backupdir=backup_240517_wKXQfP 强制修改为backupdir=xxxx%26backupfilename%3Daaaa 服务器主机会生成xxxx文件夹下的aaaa-1.sql备份文件:

修改后:

GET /dz/upload/uc_server/admin.php?m=db&a=operate&t=export&appid=0&backupdir=xxxx%26backupfilename%3Daaaa HTTP/1.1

说明:

%26 代表字符 &,而 %3D 代表字符 =。解码后,它会变成:

backupdir=xxxx&backupfilename=aaaa

  • backupdir 是一个参数,其值为 xxxx。这表示备份目录的路径。
  • backupfilename 另一个参数,其值为 aaaa。这是备份文件的名字。


模仿攻击者注册用户进行登录(前面直接从后台注册的test用户):

攻击者在dz论坛模块上发布帖子(如:刚建的“网络安全”模块),帖子内容要诱导管理员登录点击查看;发帖时,一定要添加一个网络图片,链接设置为:

http://10.0.0.101:90//dz/upload/uc_server/admin.php?m=db&a=operate&t=export&appid=0&backupdir=xxxx%26backupfilename%3Daaaa

(此链接为攻击者自己搭建的dz网站,通过管理员后台UCenter处于登录会话状态并点击查看帖子,从而建立会话,使攻击者自己的dz网站目录下生成目标主机的备份文件)

 模拟管理员登录后查看此贴:

(需管理员后台UCenter处于登录会话状态)

管理员打开查看此贴子就会在攻击者生成xxxx文件夹及下的aaaa-1.sql文件 

 查看备份的内容:

阅览器访问(获取到网站的所有信息)

http://10.0.0.101:90//dz/upload/uc_server/data/backup/xxxx/aaaa-1.sql

 


DVWA

先改成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);
}

?>

修改密码为123456,点Change修改提交:

 修改成功:

http://10.0.0.101:90/dvwa/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#

攻击者通过修改url直接修改密码:

(url上的password‘123456’修改为了admin,阅览器重新访问)

http://10.0.0.101:90/dvwa/vulnerabilities/csrf/?password_new=admin&password_conf=admin&Change=Change#

 修改成功:


因不需要输入原密码,攻击者自己修改密码构造恶意链接,通过发帖、投诉的形式发给公司,当管理员登陆后台看到攻击者的投诉,点击帖子就会把管理员密码直接修改为admin。

也可以通过xss的payload改成csrf的链接,xss钓鱼链接改成修改密码的链接。


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
            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);
}

?>

源代码中:$_SERVER[ 'HTTP_REFERER' ]

做了Referer头校验但未token校验

 做了Referer头校验,不容易进行伪造:

 通过火狐阅览器插件hackbar进行伪造Referer:


 dvwa改成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();

?>

源代码中:

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

做了token校验

token值只能使用一次,修改一次失效:

带token基本无法使用csrf 漏洞攻击。可以尝试其他方式渗透。


6、攻击试验

  • 自解压缩包

  • dz数据库备份

  • 修改密码、添加帐号

  • 命令执行

压缩包也存在CSRF漏洞:

1.点击右键选择“添加压缩文件

2.勾选 创建自解压格式压缩文件

 3。然后在压缩包高级菜单里面,点击设置【自解压选项】如图

  4.解压前运行木马文件和解压后跳转csrf网页设置:

​​​​​​​

 5.设置为全部隐藏

 

 6.受害者通过点击压缩包文件自动执行木马文件及跳转csrf恶意链接


7、防范方法

  • 校验http referer字段

  • 添加token值

  • 白名单


声明:

  • 此文章只做技术研究,谨遵守国家相关法律法规,请勿用于违法用途,如果您对文章内容有疑问,可以尝试留言私信,如有侵权请联系小编处理。
  • 35
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSRF(Cross-Site Request Forgery)攻击又称为跨站请求伪造或者被动式攻击攻击者通过伪造合法用户的请求发送到Web应用程序,从而达到不正当的目的。攻击者通常需要诱导用户执行某些操作(如点击链接、访问网站等),以触发CSRF攻击CSRF攻击的工作原理攻击者构造一个恶意请求,然后诱导用户访问带有恶意请求的页面。当用户访问该页面时,浏览器会自动发送请求到Web应用程序,由于请求中包含了用户的合法身份认证信息(如cookie等),Web应用程序无法区分该请求是否是用户本人的操作,从而执行了攻击者构造的恶意请求。 例如,攻击者可以在某个社交网站上发布一条欺骗性的链接,诱导用户点击该链接。当用户点击链接后,浏览器会自动向Web应用程序发送一条请求,该请求中包含了用户的身份认证信息和攻击者构造的恶意请求。由于Web应用程序无法判断该请求是否是用户本人的操作,因此会执行该恶意请求,从而导致CSRF攻击成功。 为了防止CSRF攻击,开发者可以采取以下措施: 1. 在关键操作(如修改密码、转账等)中增加CSRF令牌验证,确保请求是由合法用户发出的。 2. 对用户输入的数据进行有效的过滤和验证,避免恶意请求被执行。 3. 不要在GET请求中执行关键操作,避免恶意链接导致的攻击风险。 4. 使用HTTPS协议加密用户的身份认证信息,避免信息被篡改或窃取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值