2024 年 11 月 21 日星期四,在标准中:
- HTTP 饼干(cookies):是由Javascript或 HTTP 服务器设置的一小段数据,对于在无状态的万维网系统中维护状态至关重要。一旦设置,网络浏览器将在每个适当范围的 HTTP 请求中继续转发它们,直到它们过期。
- 代码示例及问题引出:原本忽略饼干功能的随意行为,因遇到一段无害的 Javascript 代码
const favoriteCookies = JSON.stringify({ ginger: "snap", peanutButter: "chocolate chip", snicker: "doodle", }); document.cookie =cookieNames=${favoriteCookies};而引发问题。该代码将 JSON 数据保存为会话饼干,虽在浏览器中运行良好,但在使用Go 标准库时却导致解析错误,引发一系列问题。 规范(RFC)相关内容:
- RFC 2109(1997)、RFC 2965(2000)和 RFC 6265(2011)及更新草案:定义了饼干值的相关内容,包括服务器发送和浏览器接受饼干值的规则等,但存在服务器应发送和浏览器应接受不一致、未限制可接受饼干值范围及未明确处理
Cookie头的标准库行为等问题。
- RFC 2109(1997)、RFC 2965(2000)和 RFC 6265(2011)及更新草案:定义了饼干值的相关内容,包括服务器发送和浏览器接受饼干值的规则等,但存在服务器应发送和浏览器应接受不一致、未限制可接受饼干值范围及未明确处理
各浏览器行为:
- Firefox:其有效饼干值代码接受五个 RFC 建议服务器不应发送的字符:
0x09(水平制表符)、0x20(空格)、0x22(双引号)、0x2C(逗号)、0x5C(反斜杠),最初是为与 Chrome 保持一致,且有network.cookie.blockUnicode设置。 - Chromium:有效饼干值代码比 Firefox 更具限制性,拒绝接受
0x09(水平制表符),但接受空格、双引号、逗号、反斜杠和 Unicode 字符。 - Safari(WebKit):因代码埋在闭源的
CFNetwork中无法获取其饼干存储代码,但通过运行 Javascript 测试发现,它接受0x09(水平制表符)、0x20(空格)、0x22(双引号)、0x5C(反斜杠),但不接受0x7F(删除)和0x80 - FF(高 ASCII / Unicode)字符,且遇到控制字符时不忽略整个饼干,而是接受到该字符之前的部分,还发现了一个奇怪的 Safari 错误,设置值为--, --的饼干会修剪逗号周围的空格。
- Firefox:其有效饼干值代码接受五个 RFC 建议服务器不应发送的字符:
各标准库行为:
- Golang:Golang 的 cookie 代码相对接近 RFC 中服务器发送
Set-Cookie的措辞,仅因0x20(空格)和0x2C(逗号)在实际中常见而允许,在处理饼干时会遇到困难,如运行此代码会隐形丢弃浏览器接受的饼干。 - PHP:许多语言如 PHP 没有原生解析饼干的函数,通过设置饼干的代码测试发现,其在控制字符方面行为混乱,
0x00 - 0x09正常,0x0D(回车)也可,但0x10(数据链路转义)和0x7F(删除)会导致 400 错误请求。 - Python:
import http.cookies,在SimpleCookie.load()中隐形放弃加载不理解的饼干,对控制字符的处理非常不一致和不可预测,如设置raw_cookie = f"cookie{hex(i)}={chr(i)}",很多控制字符的饼干会被隐形丢弃,部分会加载不正确。 - Ruby:
require "cgi",通过代码测试发现 Ruby 库在解析时似乎接受每个字符,然后从饼干罐中取出时进行百分编码,可能是最优行为,但可能与通过document.cookie设置饼干的预期不符。 - Rust:使用
use cookie::Cookie;,查看流行的cookiecrate,默认配置下对处理饼干非常宽容,接受任何 UTF - 8 字符串。
- Golang:Golang 的 cookie 代码相对接近 RFC 中服务器发送
- 实际影响及解决思路:浏览器和语言之间的行为差异在现实世界中造成了很多问题,如手动测试时第三方库更新导致网站访客收到损坏的饼干并被锁定,许多知名网站如 Facebook、Netflix 等都受到影响。解决此问题非常困难,在浏览器端阻止这些饼干虽被考虑但因各国情况复杂而未实施,在服务器端修复虽可行但影响范围广且难以解决,真正的解决办法可能在于IETF HTTP 工作组更新饼干规范,明确浏览器、编程语言和框架处理饼干处理的步骤,使其更加严格和一致。
- 总结表格:对各浏览器和语言在处理控制字符(CTLs)等方面的行为进行了对比总结,包括
htab、space、dquote、comma、backslash、delete、0x80 - FF(和 Unicode)等方面在不同规范和浏览器、语言中的情况。 - 感谢:感谢在研究过程中提供帮助的人员,如 Po - Ning Tseng、Dan Veditz 等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。