攻击成功需要同时满足以下几个条件:
- POST 请求提交表单后端没做转义直接入库。
- 后端从数据库中取出数据没做转义直接输出给前端。
- 前端拿到后端数据没做转义直接渲染成 DOM。
持久型 XSS 有以下几个特点:
- 持久性,植入在数据库中
- 盗取用户敏感私密信息
- 危害面广
3.如何防御
对于 XSS 攻击来说,通常有两种方式可以用来防御。
1) CSP
CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。
通常可以通过两种方式来开启 CSP:
- 设置 HTTP Header 中的 Content-Security-Policy
- 设置 meta 标签的方式 <meta http-equiv="Content-Security-Policy">
这里以设置 HTTP Header 来举例:
- Content-Security-Policy: default-src 'self'
- Content-Security-Policy: img-src https://*
- Content-Security-Policy: child-src 'none'
如需了解更多属性,请查看Content-Security-Policy文档
对于这种方式来说,只要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,并且 CSP 的兼容性也不错。
2) 转义字符
用户的输入永远不可信任的,最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠进行转义
- function escape(str) {
- str = str.replace(/&/g, '&')
- str = str.replace(/</g, '<')
- str = str.replace(/>/g, '>')
- str = str.replace(/"/g, '&quto;')
- str = str.replace(/'/g, ''')
- str = str.replace(/`/g, '`')
- str = str.replace(///g, '/')
- return str
- }
但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。
- const xss = require('xss')
- let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
- // -> <h1>XSS Demo</h1><script>alert("xss");</script>
- console.log(html)
以上示例使用了 js-xss 来实现,可以看到在输出中保留了 h1 标签且过滤了 script 标签。
3) HttpOnly Cookie。 (编辑:宿州站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|