xss攻击的两大要素:
攻击者提交恶意代码;
浏览器执行恶意代码。
常见防御手段:
1.输入过滤
在用户提交时,由前端过滤输入,然后提交到后端,是否可行? 答案是 不可行。一旦攻击者绕过前端过滤,直接构造请求,这样就可以提交恶意代码了。 后端在写入数据库前进行过滤,然后把 安全的 内容返回给前端,是否可行? 答案是 不可行。因为,在写入数据库前进行输入过滤虽然可以过滤掉一部分内容,但是用户的使用场景是很复杂的,我们很难判断出内容会输出到哪里,一旦用户输入的内容经过了转码,客户端就需要进行反转码,而前端不同的位置所需要的编码也是不同的。因此输入侧过滤虽然能够在某些情况下解决 XSS 问题,但是会引入很大的不确定性和乱码问题,所以应当尽量避免使用这种方法。 当然,对于明确的输入类型,例如数字、URL、电话号码、邮件地址等内容,进行输入过滤还是必要的。
2.防止执行恶意代码
存储型和反射型XSS 都是在服务端取出恶意代码后,插入到响应 HTML 中,攻击者可以编写的数据 被内嵌到 代码 中,被浏览器执行。
预防这两种漏洞,有两种常见的做法:
改成纯前端渲染,把代码和数据分隔开;
对 HTML 做充分转义。
前端渲染:目前主流框架采用的 SPA 的方式,我们会明确告诉浏览器:下面要设置的内容是文本(.innerText),还是属性(.setAttribute),还是样式(.style)等等。浏览器不会轻易被欺骗,执行与其外的代码。
但是对于有高性能要求,或者是有 seo 需求的页面,仍然要面对拼接 HTML 的问题。
转义:如果拼接 HTML 是必要的,就需要采用合适的转义库对 HTML 模版的各处插入点进行充分的转义。 常见的模版引擎有 ejs 等,对于 HTML 转义通常只有一个规则,就是把 & < > " ' / 这几个字符转义掉。确实可以起到一定的防护作用,但还不够完善。
3.拒绝危险输入(针对DOM型 XSS 攻击)
在使用 .innerHTML、.outerHTML、document.write() 是要特别小心,不要把不可信的数据作为 HTML 插入到网页,尽量使用 .textContent、.setAttribute() 等。 如果是使用 Vue / React 时,不要使用 v-html / dangerouslySetInnerHTML ,在前端避免 innerHTML、outerHTML 的 XSS 隐患; DOM 中的内联事件监听器,如 location、onclick、onerror、onload,<a> 标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等都能把字符串作为代码运行,如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,务必谨慎使用。
4.其他XSS防范措施
1).输入内容长度控制
对于不受信任的输入,都应该先定一个合理的长度。虽然无法完全防止 XSS 的发生,但是可以增加 XSS 攻击的难度。
2).HttpOnly
对敏感的 cookie 设置 HttpOnly,禁止 JavaScript 访问这些信息,攻击者在完成 XSS 攻击后也无法窃取敏感信息。
3).内容安全策略(Content Security Policy,CSP)
CSP 在 XSS 的防范中可以起到以下的作用:
禁止加载外域代码,防止复杂的攻击逻辑;
禁止外域提交,网站被攻击后,用户的数据不会泄漏到外域;
禁止内联脚本执行;
禁止未授权的脚本执行;
合理使用上报可以及时发现 XSS,利于尽快修复问题。
可以使用以下两种方式开启内容安全策略:
HTTP Header 中的 Content-Security-Policy
<meta http-equiv="Content-Security-Policy"
帖子还没人回复快来抢沙发