缓存如何工作?
计算机科学中的所有形式的缓存,无论是CPU缓存,HTTP Web Server缓存,数据库缓存等等,都旨在加快响应速度,以响应任何请求。这样做有助于最大程度地减少正在主动缓存的组件上的负载。
由于这个原理,缓存往往位于客户端/用户与服务器/组件之间。为了理解Web缓存中毒,了解这一点非常重要。在网络的生态系统中,使用的缓存类型可能会有所不同。一些示例包括但不限于:
- 记忆快取
- 漆
- CDN(即Akamai,MaxCDN,AWS)

继续,对缓存的任何引用都是在Web应用程序缓存的上下文中进行的,就像上面提到的那样。
缓存背后的想法非常简单。将“答案”(响应)静态存储到经常被请求的“问题”(请求),从而无需重新计算繁重的请求。缓存系统需要至少具有两个关键功能:
- 为其缓存项目(即文件,HTTP请求等)的时间
- 确定请求是命中高速缓存(因此快速响应)还是错过高速缓存(因此需要询问应用程序)
我们不太担心第一种选择。第二个选项可以通过使用键值存储来解决,这听起来很简单,但是实现起来确实很棘手。这里的问题是确定密钥中包含什么,以确定密钥是否唯一。
例子
想象一下,我们是一个始终位于同一域的简单站点的缓存系统 example.com。在这种情况下,将端点用作键将非常有用:
要求
POST //example.com/stats?page=1 HTTP/1.1
Host: example.com
Accept-Language: en-US
响应
HTTP/1.1 200 OK
<h1>统计页1</h1>
<p>语言:en-US</p>
这意味着我们现在可以为下一个请求路径的用户缓存该响应 /stats?page=1:
快取
钥匙 | 价值 |
---|---|
stats?page = 1 | 统计页1 语言:en-US |
您可能会注意到,缓存系统会将以下两个请求视为相同。但是,那 接受语言
标头略有不同。
请求1
POST //example.com/stats?page=1 HTTP/1.1
Host: example.com
Accept-Language: en-US
请求2
POST //example.com/stats?page=1 HTTP/1.1
Host: example.com
Accept-Language: de
这是一个问题,因为:
- 即使客户要求内容为德语,该网站也将以英语(美国)进行响应,从而导致视觉错误。
- 无键输入(接受语言)反映在页面中。
因此,如果我们发送带有 跨站脚本 有效负载反而像这样:
POST //example.com/stats?page=1&cachebust=1 HTTP/1.1
Host: example.com
Accept-Language: <script>警报(document.domain)</script>
并且缓存被更新。
钥匙 | 价值 |
---|---|
stats?page = 1&cachebust=1 | <h1>Stats Page 1</h1> <p>Language: <script>警报(document.domain)</script></p> |
这意味着 任何 访问URL的用户 //example.com/stats?page=1&cachebust=1 将返回缓存的值。这包括恶意负载,而应用程序尚未意识到,因此会利用用户的浏览器。
补救缓存中毒攻击
防御高速缓存中毒攻击可能非常棘手。完全禁用缓存是一种对大多数人不可行的方式,这是可以理解的。但是,一些有用的方法是:
- 大量缓存静态响应,例如 * .js , * .css , * .png 文件,博客文章,登录页面或任何始终相同的页面。
- 确保您不受跨站点脚本攻击的威胁,因此即使发生此类漏洞,也无法利用用户的浏览器。
- 了解并限制进行缓存的位置。您是否正在使用实现自己的缓存的框架?如果是这样,您可能要禁用该功能并在单个点(例如CloudFlare)处处理缓存。
- 避免将用户输入(即HTTP标头)用作缓存键。
结论
最后,尽管上述所有内容看起来都很艰巨, 网络应用扫描仪 如Acunetix可以检测 Web缓存中毒 as well as 跨站脚本 精确定位。
这将 剧烈地 减少发现此类漏洞所需的时间,从而帮助您在攻击者发现它们之前修复它们。
Source://www.acunetix.com/blog/