什么是跨站脚本攻击 XSS?

160 阅读4分钟

本文首发于个人网站:「一名前端攻城师的个人修养」

同源策略可以隔离不同源站点的 DOM 交互、页面数据和网络通信。严格的同源策略会更加保证安全,但是也束缚了 Web。因此需要在安全性与便捷性之间找到一个平衡点,因此浏览器默认可以引用任意第三方资源,但是却存在 XSS 攻击风险,于是浏览器又通过 CSP 策略来加以限制。

什么是 XSS 攻击

XSS 全称为 Cross Site Scripting,为了与 CSS 简称区分,因此我们对其简称为 XSS。

XSS 攻击是指黑客向 HTML 文件或者 DOM 中注入恶意脚本,从而在用户浏览页面时利用注入的恶意脚本对用户实施攻击的一种手段。

最开始的时候,XSS 攻击是通过跨域实现的,所以叫做跨域脚本。但是技术发展到现在,向 HTML 或者 DOM 中注入恶意代码的方式已经越来越多,并不已经局限于跨域注入脚本,只是 XSS 这个名字沿用至今。

当页面被注⼊了恶意 JavaScript 脚本时,浏览器⽆法区分这些脚本是被恶意注入的还是正常的页面内容,所以恶意注入 JavaScript 脚本也拥有所有的脚本权限。而注入的恶意脚本则可以进行下列这些操作:

  • 窃取 Cookie 信息。
  • 监听用户行为。
  • 修改 DOM。
  • 在页面中生成浮窗广告。
  • ……

恶意脚本是如何注入的

通常有三种方式注入恶意脚本:

  1. 存储型 XSS 攻击。
  2. 反射型 XSS 攻击。
  3. 基于 DOM 的 XSS 攻击。

存储型 XSS 攻击

存储型 XSS 攻击大致需要经过下列三个步骤:

  1. 黑客利用站点漏洞将恶意脚本提交到网站服务器的数据库中。
  2. 用户向网站请求了包含恶意脚本的页面。
  3. 当用户浏览该页面时,恶意脚本就会将用户的 Cookie 信息等数据上传到其他服务器。

反射型 XSS 攻击

在⼀个反射型 XSS 攻击过程中,恶意 JavaScript 脚本属于用户发送给网站请求中的⼀部分,随后网站又把恶意 JavaScript 脚本返回给用户。当恶意 JavaScript 脚本在用户页面中被执⾏时,黑客就可以利用该脚本做一些恶意操作了。

需要注意的是,Web 服务器不会存储反射型 XSS 攻击的恶意脚本。

基于 DOM 的 XSS 攻击

基于DOM 的 XSS 攻击并不涉及页面的 Web 服务器。具体而言,黑客通过各种⼿段将恶意脚本注入用户页面中。比如通过网络劫持在页面传输过程中修改 HTML 页面的内容,这种劫持类型很多,可以通过 WiFi 路由器劫持,可以通过本地恶意软件劫持……它们的共同点是在 Web 资源传输过程或者在用户使用页面的过程中修改 Web 页面的数据。

如何阻止 XSS 攻击

前面讲过,存储型 XSS 攻击和反射型 XSS 攻击都是需要经过 Web 服务器来处理的,因此可以认为这两种类型的漏洞是服务端的安全漏洞。

基于 DOM 的 XSS 攻击全部都是在浏览器端完成的,因此基于 DOM 的 XSS 攻击是属于前端的安全漏洞。

但无论是何种类型的 XSS 攻击,它们都有⼀个共同点,那就是首先向浏览器中注⼊恶意脚本,然后再通过恶意脚本将用户信息发送至黑客部署的恶意服务器上。

所以要阻止 XSS 攻击,我们可以通过阻止恶意 JavaScript 脚本的注入和恶意消息的发送来实现。

服务器对输入脚本进行过滤或转码

我们可以在服务器端对关键字符进行转码:

code:<script>alert('你被 xss 攻击了')</script>

过滤后只留下了:

code:

充分利用内容安全策略 CSP

CSP 大致有如下几个功能:

  • 限制加载其他域下的资源⽂件,这样即使黑客客插入了恶意 JavaScript 脚本,该脚本也是⽆法被加载的。
  • 禁止向第三方域提交数据,这样用户数据不会外泄。
  • 进制执行内联脚本和未授权的脚本。
  • 提供上报机制,可以帮我们尽快发现存在哪些 XSS 攻击,以便尽快修复问题。

使用 HttpOnly 属性

许多的 XSS 攻击都是为了盗用 Cookie,因此可以通过 HttpOnly 属性来保护 Cookie 的安全。

通常服务器可以通过 HTTP 响应头将某些 Cookie 设置为 HttpOnly 标志。

如在 HTTP 响应头中的 set-cookie 字段的末尾使用了 HttpOnly 来标记 Cookie。这样被标记的 Cookie 只能使用在 HTTP 请求中,无法通过脚本代码来读取这段 Cookie。