这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
在上一篇文章中,我们知道了在现在的web领域中存在哪些攻击,大体上建立了一个脉络,在这一篇文章中就准备详细聊聊关于 XSS攻击 的内容,废话不多说,开搞!
什么是XSS攻击
XSS攻击(Cross-Site Scripting)翻译过来就是 跨站脚本攻击,属于一种 代码注入 的攻击,攻击者将恶意代码注入到被攻击的网站中使其运行,从而达到攻击的目的
XSS攻击本质上是由于对客户端的输入没有做好 检验与过滤 而产生的,导致其中包含的恶意代码未被剔除掉,通常客户端的输入来源有以下几种
- 来自用户的UGC信息
- 来自第三方的链接
- URL 参数
- POST 参数
- Referer (可能来自不可信的来源)
- Cookie (可能来自其他子域注入)
当恶意输入被服务器接收后,XSS就可以利用这些恶意输入进行代码注入,常见的注入主要有以下几种方式:
- 将插入的字符串转义为 HTML标签 进行解析,从而可以增加标签执行恶意代码
- 通过在 href、src 属性中加入 javascript: 字符串,从而执行恶意代码
- 在标签属性中,恶意内容包含 引号,从而突破属性值的限制,注入其他属性或者标签
- 在 onload、onerror、onclick 等事件中,注入不受控制代码
XSS攻击的种类
XSS攻击主要有三种类型
- 存储型
- 反射型
- DOM型
接下来依次讲解关于它们的内容
存储型
这种类型常见于拥有类似 评论功能 的网站,攻击者可以将带有恶意代码的评论内容发送给服务器,服务器保存之后,客户端再次请求页面时,会将包含有恶意代码的内容拼接在文档中,从而导致浏览器去执行恶意代码,最终达到攻击者的目的
这种方式的攻击步骤简单归纳如下
- 黑客在评论内容中加入恶意代码
- 服务器接收恶意代码的评论内容
- 再次响应页面时,将恶意代码意外地拼接在了页面中
- 浏览器接收到含有恶意代码的页面,意外地执行了恶意代码,从而达到攻击者目的
反射型
这种方式主要是通过将恶意代码拼接在 url 上,当服务器接收到这个url时,会意外地将恶意代码取出并拼接在返回的html文档中,然后浏览器就会意外地执行恶意代码,最终达到攻击的目的
这种方式与存储型主要区别在于恶意代码存放的位置不同,存储型是放在数据库中,而反射型是放在url上
DOM型
这种方式也是将恶意代码拼接在url上,但与反射型不同的是,恶意代码的取出与执行 完全 是由前端js执行,也就是与服务器无关,属于纯粹的前端js漏洞
XSS攻击的防范
XSS攻击的危害是非常大的,由于攻击者是直接通过源站进行攻击,那么像cookie一类的身份验证标识都可以被攻击者利用,因此可以将cookie的 http-only 打开,防止被恶意代码获取
由于XSS攻击属于代码注入一类的攻击,因此对于用户输入的校验和过滤是肯定必不可少的,需要注意的是,这里的检验 前后端 都需要做,缺一不可
针对不同的攻击类型,我们需要做的防范还不太一样,对于存储型和反射型,由于它们是属于服务端侧的漏洞,因此有以下两种方式来防范
- 纯前端渲染,例如SPA,这样就可以完全避免这两种类型的攻击了
- 对HTML插入的内容进行充分转义,一般情况下,对 & < > " ' / 这几个字符进行转义就可以了,需要注意的是,对于HTML内容的转义是非常复杂的,在不同的上下文中需要采用不同的转义规则,如 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等,否则就会出现乱码的情况
针对DOM型的防范有如下几点
- 在使用 .innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML标签 插到页面上,而应尽量使用 .textContent、.setAttribute() 等
- 如果用 Vue/React 技术栈,尽量不使用 v-html/dangerouslySetInnerHTML 功能
- DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等,a标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免
结语
XSS攻击在web攻击中属于比较有名的一个类型,另一个类型则是CSRF攻击,在下一篇文章中就准备好好聊聊它,完结,撒花~