
CSRF初探

简介
跨站请求伪造 (Cross-Site Request Forgery, CSRF),也被称为 One Click Attack 或者 Session Riding ,通常缩写为CSRF,是一种对网站的恶意利用。尽管听起来像XSS,但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
分类
资源包含
资源包含类型的CSRF攻击归结为通过控制HTML标签(例如<image>、<audio>、<video>、<object>、<script>等)所包含的资源发送GET请求的攻击。
由于缺少对Cookie的源点检查,此类别CSRF攻击甚至可以不使用XSS,而直接由任何攻击者控制的站点或站点本身执行。此类型仅限于GET请求,因为这些是浏览器对资源URL唯一的请求类型。这种类型的主要限制是它需要错误地使用安全的HTTP请求方式。
基于表单的CSRF
通常在正确使用安全的请求方式时看到。攻击者创建一个想要受害者提交的表单; 其包含一个JavaScript片段,强制受害者的浏览器提交。
该表单可以完全由隐藏的元素组成,以致受害者很难发现它。
如果处理cookies不当,攻击者可以在任何站点上发动攻击,只要受害者使用有效的cookie登录,攻击就会成功。如果请求是有目的性的,成功的攻击将使受害者回到他们平时正常的页面。该方法对于攻击者可以将受害者指向特定页面的网络钓鱼攻击特别有效。
XMLHttpRequest
XMLHttpRequest可能是最少看到的方式,由于许多现代Web应用程序依赖XHR,许多应用花费大量的时间来构建和实现这一特定的对策。
基于XHR的CSRF通常由于SOP而以XSS有效载荷的形式出现。没有跨域资源共享策略 (Cross-Origin Resource Sharing, CORS),XHR仅限于攻击者托管自己的有效载荷的原始请求。
这种类型的CSRF的攻击有效载荷基本上是一个标准的XHR,攻击者已经找到了一些注入受害者浏览器DOM的方式。
原理分析
CSRF就是Client SSRF(确信)
简单实例
假设一个有CSRF攻击漏洞的站点csrf.com下存在这样一个接口transfer.php
1 |
|
这段代码的功能是当用户成功登录时(持有cookie),可以调用本接口向指定人员转账。
如果一名用户在浏览其他网页时,始终保持着这个页面的登陆状态(cookie没过期),然后遇到了一个有问题的网站。例如一个被XSS攻击的网站,被注入了恶意代码<img src = http://csrf.com/transfer.php?to='JerRyWu'&money=1000>
,这样,当用户访问了这个站点,一旦开始解析图片资源,就会向JeRyWu转1k元。这是一种较为简单同时也较为典型的XSS+CSRF攻击。
CSRF漏洞挖掘
- 抓取一个正常请求的数据包,如果没有Referer字段和token,那么极有可能存在CSRF漏洞
- 如果有Referer字段,但是去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。
- 利用工具进行CSRF检测。如:CSRFTESTER,CSRF REQUEST BUILDER等
防御
验证 Referer/Content-Type
HTTP Header中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果攻击者要对银行网站实施CSRF攻击,他只能在他自己的网站构造请求,当用户通过攻击者的网站发送请求到银行时,该请求的 Referer 是指向攻击者自己的网站。因此,要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值,然后拒绝掉来自其他站点的请求即可。
这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷
但与此同时,虽然Referer 的值由浏览器提供,以及HTTP协议对此做出了明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,这让人很不安心,例如如果HTTP请求被拦截了该怎么办。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,攻击者完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。即便是使用最新的浏览器,在不考虑0day的情况下,哪怕攻击者无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。这意味着验证Refer字段值的防御方式在某些情境下会无法实行。令人感慨。
通过CSRF-token或者验证码来检测用户提交
CSRF 攻击之所以能够成功,是因为攻击者可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。防御CSRF的关键在于在请求中放入攻击者所不能伪造的信息,且该信息不存在于cookie中。
在参数中设置CSRF Token
可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求
这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token
该方法还有一个缺点是难以保证 token本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,攻击者可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上token,攻击者可以在自己的网站上得到这个token,并马上就可以发动CSRF攻击。为了避免这一点,系统可以在添加token的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加token,如果是通向外网则不加。不过,即使这个 csrftoken不以参数的形式附加在请求之中,攻击者的网站也同样可以通过Referer来得到这个token值以发动CSRF攻击。这也是一些用户喜欢手动关闭浏览器Referer功能的原因
在HTTP Header中设置CSRF Token
通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 CSRFToken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去
然而这种方法的局限性非常大。XMLHttpRequest请求通常用于Ajax方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,重构会变得极为折磨。
对于用户修改删除等操作最好都使用POST操作(例如采用Restful API)
避免全站通用的Cookie,严格设置Cookie的域
Reference
demo
WipingOutCSRF
NeatTricksToBypassCSRFProtection
https://www.cnblogs.com/pengdai/p/12164754.html
- Title: CSRF初探
- Author: 7erry
- Created at : 2023-08-11 00:00:00
- Updated at : 2023-08-11 00:00:00
- Link: http://7erry.com/2023/08/11/CSRF初探/
- License: This work is licensed under CC BY-NC 4.0.