Web缓存中毒(Web Cache Poisoning)是一种攻击技术,攻击者通过操纵Web应用程序的缓存系统,将恶意或欺骗性内容注入到合法的缓存中,以欺骗用户或绕过安全控制。
Web缓存中毒的原理是利用缓存服务器在接收到请求后,将响应保存在缓存中并将相同响应返回给后续请求的用户。攻击者通过在请求中操纵参数、头部或URL等,使缓存服务器错误地将恶意或欺骗性响应存储在缓存中。当其他用户发起相同请求时,缓存服务器将返回被注入的恶意响应,从而达到攻击的目的。
恶意内容传播:攻击者可以注入恶意脚本、恶意链接或恶意文件,使用户的浏览器执行恶意代码或下载恶意文件,导致用户设备被感染或受到其他安全威胁。
身份盗窃:攻击者可以伪造登录页面或欺骗性表单,诱使用户输入敏感信息,如用户名、密码、信用卡信息等,从而窃取用户的身份凭证。
网络钓鱼:攻击者可以欺骗用户访问虚假的网站或页面,从而窃取用户的敏感信息或诱导用户进行非法行为。
网站篡改:攻击者可以篡改网站内容,包括更改产品价格、修改订单信息、发布虚假公告等,导致用户受到经济损失或误导。
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a.">"
HTTP/1.1 200 OK
Cache-Control: public
"/cms/social.png" />
tips;X-Forwarded-Host(XFH)标头是事实上的标准标头,用于标识客户端在主机 HTTP 请求标头中请求的原始主机。
原理:X-Forwarded-Host标头的值用于动态生成Open Graph图像URL,然后将其反映在响应中。并且X-Forwarded-Host标题通常是不加密的。在此示例中,缓存可能容易受到包含简单XSS有效负载的响应的污染。
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
原理:当网站使用无密钥header动态生成需要导入资源的URL时,攻击者将适当的header的值更改为他们控制的域,如构造恶意Js文件执行恶意代码。
当恶意URL的响应被缓存,则攻击者的js将被导入,并在其请求具有匹配的缓存密钥的任何用户的浏览器会话中执行。
GET /blog/post.php?mobile=1 HTTP/1.1
Host: innocent-website.com
User-Agent: Mozilla/5.0 Firefox/57.0
Cookie: session=gyfopPwvyKOx7c796xHpJuE41V55O10m; fehost=prod-cache-01" -alert(1)-"fgsfg
Connection: close
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Web cache poisoning with an unkeyed cookie
tips:X-Forwarded-Scheme头,指示原始请求是通过HTTP还是HTTPS发送的。
例如,当客户端使用HTTPS访问代理服务器,并且代理服务器转发请求到后端应用程序时,代理服务器可以添加X-Forwarded-Scheme: https头,以指示后端应用程序该请求是通过HTTPS发送的。
原理:当缓存服务器通过X-Forwarded-Scheme头识别到主机通过http而不是https发送请求,通过Location: https://exploit 进行跳转,而跳转的时候读取的是X-Forwarded-Host头传递的数据,可通过构造恶意url资源,造成了缓存中毒。
tips:X-Host是一个自定义的HTTP请求头部字段,通常用于在请求中指定主机名或域名。
原理:通过排查发现User-Agent为键值,当缓存的User-Agent和受害者一样即可造成缓存利用。
原理:通过观察请求包发现,可以通过X-Forwarded-Host传入服务器地址,前端读取X-Forwarded-Host后通过initGeoLocate('//' + data.host + '/resources/json/geolocate.json')调用json,而json传入的值可以在页面进行展示。
X-Original-URL 用来传递原始url数据。通过DOM进行利用。
UTM参数的全名是Urchin Tracking Module。当我们设定好UTM参数,即可追踪网站活动的流量来源,不同流量来源所占的比例等。
来源(utm_source):用来标识流量来源网站、搜索引擎或其他来源。示例:utm_source=baidu
媒介(utm_medium):用来标识媒介,比如电子邮件或每次点击费用。示例:utm_medium=cpc
名称(utm_campaign):用来标识特定的产品推广活动。示例:utm_campaign=summer_spread
关键字(utm_term):常见于付费关键字广告所使用的字词或是连结名称图片的替代文字。示例:utm_term=web+analysis
内容(utm_content):使用utm_content区分指向同一个网址的广告或链接。示例:utm_content=logolink或utm_content=textlink
GET /?example=123?excluded_param=
ET /?param=innocent HTTP/1.1
…
param=bad-stuff-here
tips:Fat GET 指带有请求体的 GET 请求,请求体中的参数在一些网站中会被正常处理,而且很可能不包含在缓存键中。
ET /example?param=">
GET /example?param=%22%3e%3ctest%3e
原理:受害者点击恶意URL,虽然浏览器将url进行了url编码,但是缓存服务器对请求参数做了一些解码处理,当解码结果和投毒一致,于是无法利用的反射型 xss 生效。
存键包括请求中的多个部分,而且经常会简单地进行字符串拼接后做比较。在知道了不同参数的分隔符的前提下,可以通过注入让两个不同的请求具有相同的缓存键。
Pragma: x-get-cache-key" 是一个自定义的HTTP请求头部,用于指示CDN(内容分发网络)提供商获取缓存键(Cache Key)的信息。Cache Key是CDN在缓存内容时使用的唯一标识,用于识别和检索缓存的内容。
当客户端发送带有"Pragma: x-get-cache-key"的HTTP请求时,CDN会解析该请求头部并返回与请求相关的缓存键。这样客户端可以获取到当前请求所对应的缓存键信息,用于调试、监控或其他特定需求。"Content-Length"是一个HTTP响应头部,用于指示服务器返回的响应正文的长度,以字节为单位。该头部字段通常与HTTP请求头中的"Content-Length"字段一起使用,用于确保正确传输响应数据,并帮助接收方正确解析和处理响应。
这个字符串 "%0d%0aContent-Length:%208%0d%0a%0d%0a" 是经过 URL 编码后的文本,表示 HTTP 请求头部的一部分。具体解释如下:"%0d%0a" 表示回车换行符(CRLF),即 Carriage Return (CR) 和 Line Feed (LF)。在 HTTP 协议中,CRLF 用于分隔请求头部的每一行。
"Content-Length: 8" 表示请求头部中的 Content-Length 字段,它指定请求体的长度为 8 个字节。
"%0d%0a%0d%0a" 表示两个回车换行符(CRLF),用于表示请求头部结束,之后是请求体。解题思路:抓包查找注入点,发现localize.js可控制注入点,当 cors 参数为 1,响应会反射请求中的 Origin 头。最终可导致 CRLF 攻击。通过Pragma: x-get-cache-key发现使用的缓存键,当存在 Origin 头会通过&&进行拼接,形成缓存键 X-Cache-Key: /js/localize.js?lang=en?cors=1$$Origin=x%0d%0aContent-Length:%208%0d%0a%0d%0aalert(1)。
访问login?lang=en?发现会自动跳转到login/?lang=en?,并且使用了缓存,跳转页面可通过utm_content非缓存键进行修改。最终跳到login/?lang=en?utm_content=xq%26cors%3d1$$Origin%3dx%250d%250aContent-Length%3a%25208%250d%250a%250d%250aalert(1)%23,而且该url缓存键与我们构造的攻击缓存见一致,最终使用我们精心构造响应,导致攻击成功。
判断依据:由于无法通过缓存键进行判断,可通过响应中包含了当前请求的内容以及旧请求的内容,又或者响应中出现了你在其他请求发送的内容,那么很可能使用了应用缓存。
输入验证和过滤:对所有用户输入的参数进行严格的验证和过滤,包括请求的URL、参数、Cookie等。确保输入的数据符合预期格式,避免注入恶意代码或特殊字符。
缓存策略设置:确保合理的缓存策略被采用,包括缓存的过期时间、缓存的范围和可缓存的内容类型等。避免对敏感或动态数据进行缓存。
缓存完整性校验:在缓存服务器和客户端之间进行数据传输时,使用校验和或数字签名等机制验证数据的完整性。确保缓存的内容没有被篡改。
安全的缓存存储:确保缓存服务器的安全性,包括限制对缓存服务器的访问权限、加密敏感数据、监控和审计缓存访问等。
隔离缓存和动态内容:将缓存服务器与动态内容的服务器分开部署,确保缓存服务器不会受到恶意请求的影响。
定期更新缓存:根据业务需求和数据的变化,定期更新缓存内容,避免缓存中存储过期或失效的数据。
监控和日志记录:监控缓存服务器的活动和访问情况,记录异常事件和恶意请求,及时发现并应对潜在的攻击。
安全意识培训:对开发人员和系统管理员进行安全意识培训,教育他们如何编写安全的代码、配置安全的缓存策略和处理缓存中毒攻击。