JavaScript 跨站伪造请求-CSRF

CSRF: Cross-Site Request Forgery

CSRF 概念

`定义`: 是一种对网站的而已利用,也被称之为one-click-attack 或者 session riding, 
         简写为 CSRF或XSFR,是一种挟制用户在当前已登录的web应用程序上执行非本意的操作的攻击方法.
`理解`: 攻击者盗用了你的身份, 以你的名义发送恶意请求, 对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作.
`比如`: 以你的名义发送邮件,发送消息,盗用你的账户,添加系统管理员,设置于购买商品,虚拟货币转账等.
`示例`: 攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(发邮件,发消息,甚至转账或者购买商品)。
        由于浏览器曾经认证过,所以被访问的网站会认为是真正的的用户操作而去执行,这利用了web中用户身份    验证的一个漏洞, 
        简单的身份验证只能保证请求发自某个用户的浏览器,而不能保证请求本身是用户资源发出的

CSRF 流程

CSRF 其他概念

`Cookie`是一个域服务器存储在浏览器中的一小段数据。只能被这个域访问,谁设置谁访问
`第一方cookie`:  比如登录 `www.a.com` 这个网站,这个网站设置了一个cookie, 这个Cookie也只能被`www.a.com`这个域下面的网页读取
`第三方cookie`:  比如访问 `www.a.com`这个网站,网页里有用到`www.b.com`网站中的一张图片,浏览器在`www.b.com`请求图片的时候. 
`www.b.com`设置了一个cookie,那么这个cookie只能被`www.b.com`这个域访问,反而不能被`www.a.com`这个域访问, 
因为对我们来说,我们实际上在访问`www.a.com`这个网站被设置了一个`www.b.com`这个域下的cookie,所以叫第三方cookie。
'用户和目标域名外的地址都是第三方'

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的而已代码被执行

'总结': 通过访问而已网址,恶意网址返回来JavaScript自动执行访问你之前登录的网址,由于你已经登录了,所以再次访问将会携带cookie, 
因为服务器只认有没有cookie而无法辨别请求者身份,所以会欺骗服务器,造成攻击

CSRF 防御策略及方法

CSRF攻击防御的重点是利用cookie的值只能被第一方获取,无法读取第三方的cookie值
预防CSRF的简单可行办法就是在客户端网页上再次添加一个cookie,保存一个随机数,而用户访问的时候,先读取这个cookie的值,
hash一下这个cookie值并发送给服务器, 服务器接受到用户的hash之后的值,同时取出之前设置在用户端的cookie的值,用同样的算法hash这个cookie的值
比较这2个hash的值,相同则是合法(如果用户访问了危险网站。也想带这个cookie区访问的时候,此时,因为危险网站无法获取第三方的cookie的值,
所以它也就无法hash这个随机数,所以也就会被服务器的校验过滤掉)

Session工作原理

如果把浏览器的cookie禁用了,session还能正常工作吗? =====>>>> 不能!
而初级会员卡只能在练习场挥杆)以及我的个人资料都是保存在高尔夫俱乐部的数据库里的。我每次去高尔夫俱乐部只需要出示这张高级会员卡,
俱乐部就知道我是谁了,并且为我服务了。

'高级会员卡卡号' 就是 'cookie'中的'session id'
'高级会员卡权利和个人信息'就是服务端的'session对象'

'http请求是无状态的',也就是说每次http请求都是独立的无关之前的操作的,
但是每次http请求都会将本域下的所有'cookie'作为http请求头的一部分发送给服务端,
所以服务端就根据请求中的'cookie'存放的'sessionid'去session对象中找到该会员资料了。 

当然session的保存方法多种多样,可以保存在文件中,也可以内存里
考虑到分布式的横向扩展我们还是建议把它保存在第三方媒介中,比如redis或者mongodb。
CSRF相当于恶意用户A复制了我的高级会员卡,哪天而已用户A也可以拿着这张假冒的高级会员卡去享受高级会员的权利了,而我还需要为他的行为付出代价

CSRF 攻击例子 - 1

我可以伪造某一个用户的身份给其好友发送垃圾信息,这些垃圾信息的超链接可能带有木马程序或者一些欺骗信息(比如借钱之类的)
如果CSRF发送的垃圾信息还带有蠕虫链接的话,那些接收到这些有害信息的好友万一打开私信中的连接就也成为了有害信息的散播着,
这样数以万计的用户被窃取了资料种植了木马。整个网站的应用就可能在瞬间奔溃,用户投诉,用户流失,公司声誉一落千丈甚至面临倒闭。
曾经在MSN上,一个美国的19岁的小伙子Samy利用css的background漏洞几小时内让100多万用户成功的感染了他的蠕虫,虽然这个蠕虫并没有破坏整个应用,
只是在每一个用户的签名后面都增加了一句“Samy 是我的偶像”,但是一旦这些漏洞被恶意用户利用,后果将不堪设想,同样的事情也曾经发生在新浪微博上面

CSRF 攻击例子 - 2

CSRF攻击的主要目的是让用户在不知情的情况下攻击自己已登录的一个系统,类似于钓鱼。如用户已登陆了邮箱或bbs
同时用户又在使用另外一个已经被人控制的站点,我们姑且称之为 `钓鱼网站`
这个网站上面可能因为某个图片吸引你,你去点击一下,此时可能就会触发一个js的点击事件,构造一个bbs发帖的请求,去往你的bbs发帖,
由于当前你的浏览器状态已经是登陆状态,所以session登陆cookie信息都会跟正常的请求一样,纯天然的利用当前的登陆状态
让用户在不知情的情况下,帮他们发帖或干其他事情

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 必须要满足的2个条件

`1`: 登录受信任的网站A,并在本地生成cookie
`2`: 在不登出A的情况下,访问危险网站B

CSRF 常见攻击类型

'🚀🚀 GET类型的 CSRF'
'<img src=http://wooyun.org/csrf?xx=11 />
在访问含有这个img的页面后,成功向http://wooyun.org/csrf?xx=11 发出了一次HTTP请求。
所以,如果将该网址替换为存在GET型CSRF的地址,就能完成攻击了'

'🚀🚀 POST类型的 CSRF'
<form action=http://wooyun.org/csrf.php method=POST>
  <input type="text" name="xx" value="11" />
</form>
<script> document.forms[0].submit(); </script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作

CSRF 攻击示例-银行转账

可以使 Bob 把 1000000 的存款转到 bob2 的账号下。
通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。

'Step2':黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。
Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。
但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。

'Step3': 这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: 
src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,
并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,
而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。
但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。
这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,
即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。 

CSRF 攻击的对象

CSRF攻击的对象,其实就是要保护局的对象
CSRF攻击时黑客借助受害者的cookie(session)骗取服务器的信任,但是黑客并不能拿到cookie,也看不到cookie的内容。
另外,对于服务器返回结果,由于浏览器同源策略的限制,黑客也无法解析,因此黑客无法从返回的结果中得到任何东西。
黑客能做的: '给服务器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的值,而非窃取服务器中的数据.'

所以,我们要保护的对象是那些可以直接产生数据改变的服务,而对于读取数据的服务,则不需要进行 CSRF 的保护。
比如银行系统中转账的请求会直接改变账户的金额,会遭到 CSRF 攻击,需要保护。
而查询余额是对金额的读取操作,不会改变数据,CSRF 攻击无法解析服务器返回的结果,无需保护

'增删改需要防范XSRF,而读不需要'

CSRF 漏洞检测

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

随着对CSRF漏洞研究的不断深入,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。

CSRF 防御策略

'1': 验证HTTP Refer字段
'2': 在请求地址中添加token验证
'3': 在http 投中自定义属性并验证
'4': Chrome浏览器端启用 SameSite cookie

CSRF 防御手段

'1': 尽量使用POST, 限制GET GET接口太容易被拿来做CSRF攻击,
     看第一个示例就知道,只要构造一个img标签,而img标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。
'2':  浏览器Cookie策略
'3':  加验证码,验证码,强制用户必须与应用进行交互,才能完成最终请求。在通常情况下,验证码能很好遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码。
      因此验证码只能作为一种辅助手段,不能作为主要解决方案
'4': Referer Check Referer Check在Web最常见的应用就是“防止图片盗链”。同理,
     Referer Check也可以被用于检查请求是否来自合法的“源”(Referer值是否是指定页面,或者网站的域),如果都不是,那么就极可能是CSRF攻击
'5': Anti CSRF token 业界推荐

Anti CSRF token

1. 用户访问某个表单页面。
2. 服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。
3. 在页面表单附带上Token参数。
4. 用户提交请求后, 服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。

这个Token的值必须是随机的,不可预测的。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。
另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。

CSRF的Token仅仅用于对抗CSRF攻击。当网站同时存在XSS漏洞时候,那这个方案也是空谈。所以XSS带来的问题,应该使用XSS的防御方案予以解决。
posted @ 2020-07-23 10:02  荣光无限  阅读(793)  评论(0编辑  收藏  举报