XSS,CSRF,Cookie防劫持的处理

Posted momjs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XSS,CSRF,Cookie防劫持的处理相关的知识,希望对你有一定的参考价值。

Cookie与session
HTTP天然是无状态的协议, 为了维持和跟踪用户的状态, 引入了Cookie和Session. Cookie包含了浏览器客户端的用户凭证, 相对较小. Session则维护在服务器, 用于维护相对较大的用户信息.

用通俗的语言, Cookie是钥匙, Session是锁芯.

Cookie简单理解就是钥匙, 每次去服务端获取资源, 需要带着这把钥匙, 只有自己的锁芯(资源), 才能打开.。

但是如果钥匙被别人拿了, 那别人就可以冒充你的身份, 去打开你的锁芯, 从而获取你的信息, 甚至挪用你的资金. 这是非常危险的.

XSS攻击:
其就是利用站点开放的文本编辑并发布的功能, 从而造成攻击,就是输入javascript脚本, 窃取并投递cookie信息到自己的站点.
比如攻击者以一个普通用户登录进来,然后在输入框中提交以下数据:


有了该session-id,攻击者在会话有效期内即可获得管理员的权限,并且由于攻击数据已添加入数据库,只要攻击数据未被删除,那么攻击还有可能生效,是持久性的。

Cookie的不安全就是因为这引起的。
Cookie防劫持预防
基于XSS攻击, 窃取Cookie信息, 并冒充他人身份。
1) 方法一:
给Cookie添加HttpOnly属性, 这种属性设置后, 只能在http请求中传递, 在脚本中, document.cookie无法获取到该Cookie值. 对XSS的攻击, 有一定的防御值. 但是对网络拦截, 还是泄露了.
2)方法二:
在cookie中添加校验信息, 这个校验信息和当前用户外置环境有些关系,比如ip,user agent等有关. 这样当cookie被人劫持了, 并冒用, 但是在服务器端校验的时候, 发现校验值发生了变化, 因此要求重新登录, 这样也是种很好的思路, 去规避cookie劫持.
3)方法三:
cookie中session id的定时更换, 让session id按一定频率变换, 同时对用户而言, 该操作是透明的, 这样保证了服务体验的一致性.

 

用大白话谈谈XSS与CSRF

 

CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!

如何防御?
请求令牌(一种简单有效的防御方法):
首先服务器端要以某种策略生成随机字符串,作为令牌(token),保存在 Session 里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,只有一致的时候才处理请求,处理完成后清理session中的值,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份 
令牌来防止 CSRF 有以下几点要注意:
 a.虽然请求令牌原理和验证码有相似之处,但不应该像验证码一样,全局使用一个 Session Key。因为请求令牌的方法在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。如果全局使用一个 Session Key,那么危险系数会上升。原则上来说,每个页面的请求令牌都应该放在独立的 Session Key 中。我们在设计服务器端的时候,可以稍加封装,编写一个令牌工具包,将页面的标识作为 Session 中保存令牌的键。

b.在 ajax 技术应用较多的场合,因为很有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但无论如何,请不要提供直接获取令牌值的 API。这么做无疑是锁上了大门,却又把钥匙放在门口,让我们的请求令牌退化为同步令牌。

c.第一点说了请求令牌理论上是可破解的,所以非常重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、淘宝的做法)。但这两种方式用户体验都不好,所以需要产品开发者权衡。

d.无论是普通的请求令牌还是验证码,服务器端验证过一定记得销毁。忘记销毁用过的令牌是个很低级但是杀伤力很大的错误。我们学校的选课系统就有这个问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码可以在多次请求中使用(只要不再次刷新验证码图片),一直用到。

如下也列出一些据说能有效防范 CSRF,其实效果甚微或甚至无效的做法:
a.通过 referer 判定来源页面:referer 是在 HTTP Request Head 里面的,也就是由请求的发送者决定的。如果我喜欢,可以给 referer 任何值。当然这个做法并不是毫无作用,起码可以防小白。但我觉得性价比不如令牌。

b.过滤所有用户发布的链接:这个是最无效的做法,因为首先攻击者不一定要从站内发起请求(上面提到过了),而且就算从站内发起请求,途径也远远不知链接一条。比如 <img src="./create_post.php" /> 就是个不错的选择,还不需要用户去点击,只要用户的浏览器会自动加载图片,就会自动发起请求。

c.在请求发起页面用 alert 弹窗提醒用户:这个方法看上去能干扰站外通过 iframe 发起的 CSRF,但攻击者也可以考虑用 window.alert = function(){}; 把 alert 弄哑,或者干脆脱离 iframe,使用 Flash 来达到目的。

总体来说,目前防御 CSRF 的诸多方法还没几个能彻底无解的。 作为开发者,我们能做的就是尽量提高破解难度。当破解难度达到一定程度,网站就逼近于绝对安全的位置了。

 

安全防范

CSRF(Cross-site request forgery,跨站请求伪造),是通过伪造请求,冒充用户在站内进行操作

比如,点击发帖后会进行如下GET请求

http://example.com/bbs/create_post.php?title=标题&content=内容

那么,如果我们模拟了请求的链接,那么只要有用户点击了这个链接,他就会在不知情的情况下发布了这一帖子,那么删贴,发邮件等等都可以进行伪造

http://example.com/bbs/create_post.php?title=攻击&content=哈哈

如何防范 CSRF 攻击

  • CSRF 攻击之所以能够成功:是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证
  • 所以解决办法是:在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中
  • 验证 HTTP Referer 字段
  • 关键操作只接受POST请求,因为GET请求的参数携带在URL中,很容易进行模拟,而POST请求的参数在http body中
  • 验证码,每次操作都需要用户进行互动,从而简单有效的防御了CSRF攻击,但是验证码太多,也会影响用户体验
  • 可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端来验证这个 token
  • 可以在 HTTP 头中自定义的属性里加入一个随机产生的 token,通过XMLHttpRequest,可以给所有请求加上这个token,通过XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中

注意:过滤用户输入的内容不能阻挡 CSRF,我们需要做的是过滤请求的来源

XSS(Cross Site Scripting,跨站脚本攻击),是注入攻击的一种,特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径

例如:发布评论,提交含有 JavaScript 的内容文本,如果服务器端没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本,或者是一些未授权的操作

while (true) { alert("你关不掉我~"); }

在输入框中输入document.cookie,可以直接获得cookie中的内容,所以,在重要的cookie参数中加入httpOnly属性

XSS 是实现 CSRF 的诸多途径中的一条,一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF

如何防御 XSS 攻击

理论上,所有可输入的地方没有对输入数据进行处理的话,都会存在XSS漏洞,防御 XSS 攻击最简单直接的方法,就是过滤用户的输入

可以直接对用户的输入进行 html escape

<script>window.location.href=”http://www.baidu.com”;</script>

经过 escape 之后,就不能执行了

 <script>window.location.href="http://www.baidu.com"</script> 

















以上是关于XSS,CSRF,Cookie防劫持的处理的主要内容,如果未能解决你的问题,请参考以下文章

第679期JavaScript防http劫持与XSS

php防攻击

挖洞经验 | 利用XSS和CSRF漏洞远程实现PayPal合作方网站未授权账户访问

跨站请求伪造CSRF

挖洞经验 从XSS漏洞到四步CSRF利用实现账户劫持

一文搞懂│XSS攻击SQL注入CSRF攻击DDOS攻击DNS劫持