何为CSRF攻击
Cross Site Request Forgery跨站请求攻击,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
举个例子:当用户在浏览器中同时打开一个安全网站和一个恶意网站时,恶意网站的html的代码中有一段是对应于安全网站的某一操作的,此时安全网站因为已经认证过了浏览器的信息会认为该请求是由用户发出的会运行相应的程序,导致用户在不知情的状况下产生损失。
- 当用户通过浏览器进入某一网站时,验证通过,会在用户处产生安全网站的Cookie,当用户同时访问恶意网站时,用户会带着恶意网站发出的请求再次访问安全网站,浏览器会带着该Cookie再次访问安全网站,此时安全网站会根据用户的权限处理其请求,此时恶意网站就达到其目的了。
注意
Cookie不会在退出网站后马上消失,所以即使你已经退出安全网站后,它仍然会被保存一段时间,所以即使在退出安全网站后再访问恶意网站,依然有可能会遭受攻击。
CSRF攻击如何防御
一般来说从服务端进行防御
- CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上
<input type=”hidden” name=”csrftoken” value=”tokenvalue”/>
这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。
- One-Time Tokens(不同的表单包含一个不同的伪随机值)
在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。 - 浏览器的同源策略保证其他网页无法读取到当前页面的Cookie,但是提交表单不受同源策略的控制,表单中可以设置隐藏域,在隐藏域中增加安全验证的数据,使服务器确认数据确实是来自本网站的,可以接受表单数据,否则不接受。与前面的在表单中添加token的方式相同。
<input type="hidden" name="csrf" value="xxxxx">
- 验证HTTP Referer字段,HTTP请求头中有一个字段叫Referer,它记录了HTTP请求的来源地址,在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。
何为XSS攻击
跨站脚本攻击Cross-site scripting (XSS)是一种安全漏洞,攻击者可以利用这种漏洞在网站上注入恶意的客户端代码。当被攻击者登陆网站时就会自动运行这些恶意代码,从而,攻击者可以突破网站的访问权限,冒充受害者。—— MDN
XSS攻击分为反射型和存储型:
- 反射型就是在当前HTML中注入一段恶意脚本,当发起请求后这段脚本马上执行,比如在输入框中输入<script>alert('1')</script>,如果页面没有对关键词进行过滤及代码转换,这段代码就会直接在页面上执行,弹出 1。
- 存储型就是注入型脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器上传回并执行。
- 攻击者使被攻击者在浏览器中执行脚本后,如果需要收集来自被攻击者的数据(如cookie或其他敏感信息),可以自行架设一个网站,让被攻击者通过JavaScript等方式把收集好的数据作为参数提交,随后以数据库等形式记录在攻击者自己的服务器上。
XSS攻击如何防御
- 内容安全策略(Content Security Policy)
CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。csp需要在Response Headers中添加 ,请看例子:
JS仅允许本站资源或https://apis.google.com的资源:
Content-Security-Policy: script-src 'self' https://apis.google.com
也可以在网页的<meta>中设置
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
- 对于输出到html的输入内容,采用过滤关键词的方式,把预设的关键词转换成字符实体,例如将< >转换成 < 和 >
参考文献:
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html?login=1
https://www.cnblogs.com/shanyou/p/5038794.html
https://bitsflow.org/frontend/xss-and-csrf/
https://www.cnblogs.com/coderhero/p/9046685.html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
http://www.ruanyifeng.com/blog/2016/09/csp.html
token相关知识点:
https://www.cnblogs.com/xuxinstyle/p/9675541.html