If-None-Match&ETag

If-None-Match&ETag
Att@ckxu渗透中遇到问题
今天渗透中碰到了新问题:第一次请求网站的功能点,发送请求会获得一个响应头“ETags”,而当我们第二次请求该接口时,我们会携带一个请求头“If-None-Match”,并且它的值和第一次的响应头“ETags”相同,而第二次的响应码则是304,并且在burp中无法正常返回内容(前端页面可以正常回显),而当删除该请求头时,就能像第一次一样正常请求
因为项目信息敏感,所以厚码:)
引起了我的思考,为什么会出现这种情况呢?
认识ETag
ETag
HTTP 响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web 服务器不需要发送完整的响应。而如果内容发生了变化,使用 ETag 有助于防止资源的同时更新相互覆盖(“空中碰撞”)。
如果给定 URL 中的资源更改,则一定要生成新的 ETag
值。比较这些 ETag
能快速确定此资源是否变化。
按我的理解来说,ETag就是一个标识符,用来标识当前页面是否发生变化,当请求包中的ETag和响应包中的ETag内容相同时,则表示该次请求的资源并没有发生变化
ETag: W/"<etag_value>" |
这里就会发现,渗透中遇到的这个ETag的格式就是使用弱验证器
缓存验证
也就是说,上面的情况就是用来缓存未更改的资源,我在第一次请求一个URL,响应包正常回显200,并且会带有ETag响应头;而当我第二次请求该URL时,客户端发送请求时,会将ETag放在If-None-Match请求头一起发送,并且与当前的(也就是第一次请求的)ETag进行比较,如果二者相同,则表示在这两次请求中,资源未发生更改,响应包的状态码会返回304,并且返回包中没有任何内容(这时候客户端仍然能够正常回显,因为他请求的是缓存的内容)
上面的情况只见了If-None-Match,没有见If-Match
ETag生成策略
ETag的生成策略可以由开发者自己来控制的,但一般都是较为复杂的字符串
策略 | 说明 | 特点 |
---|---|---|
文件内容的哈希值 | 如 SHA-1 或 MD5 计算响应体内容的哈希 |
精准反映资源变动(强一致性) |
资源的最后修改时间戳(mtime) | 使用文件系统的最后修改时间,如 mtime 的十六进制表示 |
性能高,但可能误判 |
文件大小 + 修改时间 | 合并大小和时间戳,如 size-timestamp 的 base64 编码 |
更准确但仍可能碰撞 |
版本号 / 数据库字段版本 | 如记录中的 version 字段或 updated_at 时间戳 |
数据驱动,适合 API |
响应体内容摘要 + 缓存层 ID | CDN 或反向代理(如 Nginx、Varnish)生成内容签名 | 多层缓存分发适用 |
随机或UUID(极少用) | 某些系统简单生成随机值 | 会导致缓存命中失败,违背 ETag 初衷 |
为什么要使用ETag
我的理解是:使用ETag之后,在请求资源为改变的情况下,进行多次请求同一个资源时,只需要返回304即可,不需要返回服务器中该资源的全部内容,对流量消耗小
使用ETag与If-None-Match的安全问题
因为是在渗透嘛,摸清楚这个东西之后,首要考虑的还是安全问题,但是搜了一下是有一个CVE
CVE-2024-38809:Spring Framework 通过条件 HTTP 请求造成 DoS 攻击
但是并没有搜到这个POC,gpt给的POC就是在请求包中的If-None-Match请求头的值中添加大量数据,导致后端在对比解析ETag时占用资源,造成DoS
If-None-Match: W/"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", W/"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", W/"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", W/"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", W/"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", W/"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", W/"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg", W/"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", W/"iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", W/"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj", W/"kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk", W/"llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll", W/"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", W/"nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", W/"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", W/"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp", W/"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", W/"rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", W/"ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss", W/"tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt", W/"uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu", W/"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv", W/"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", W/"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", W/"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", W/"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" |
但是我在谨慎尝试之后,并没有任何DoS影响,考虑以下方面
- 该漏洞是有版本限制,可能目标服务器使用的是高版本Spring,导致不存在该漏洞
- 开发者对于If-None-Match标头的大小做了限制,强制只解析一部分
与Web Cache Poisoning(缓存投毒)对比
在看这个CVE的时候,不禁让我想起来了之前一位师傅跟我讲的缓存投毒的问题,现在对比一下二者
CVE-2024-38809漏洞本质:
Spring Web会解析请求头中If-None-Match / If-Match 的 ETag,而当攻击者构造大量的ETag(也就是请求头If-None-Match所对应的值),Spring Web使用正则去解析 ETag 压力过大,最终导致DoS
Web Cache Poisoning(缓存投毒)核心机制
利用 缓存服务器(如 CDN、Nginx、Varnish) 会缓存某些 HTTP 请求(通常基于 URL、请求头等);通过构造特定请求,让缓存系统存储了带恶意内容或不该被缓存的响应;导致后续用户访问获取的是被污染的内容(恶意脚本、错误响应等);
因此二者在本质上还是有区别的,一个是DoS,一个是污染/伪造/欺骗
参考
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Reference/Headers/ETag
https://blog.csdn.net/catoop/article/details/134174653
https://zhuanlan.zhihu.com/p/162945656
https://blog.csdn.net/qq997404392/article/details/143199178