浏览器引入cookie前缀旨在保护会话安全,防止攻击者设置恶意cookie。本文将展示如何利用浏览器与服务器逻辑差异绕过cookie防护机制。
通过Unicode空白字符覆盖Cookie
RFC 6265bis引入cookie前缀强化安全机制:
- 带
__Host-
前缀的cookie必须为host-only(不可跨子域共享) - 带
__Secure-
前缀的cookie必须来自安全源
这些限制由浏览器强制执行,但浏览器与服务器在cookie编码解析上的不一致会导致微妙而危险的漏洞。根据RFC 6265,Cookie头被定义为八位字节序列而非字符序列,这意味着浏览器发送原始字节,服务器需负责解码。若双方字节解释方式不同,就会产生解析差异。
通过UTF-8编码,攻击者可伪装受限cookie(如以__Host-
开头)绕过浏览器保护。浏览器可能将其视为非受限cookie,但服务器解码规范化后可能将其识别为受保护cookie。
以下为概念验证代码:
|
|
该带空白前缀的cookie被浏览器视为非前缀非受限值,因此会发送到目标域的所有子域。
测试发现Django、ASP.NET等服务器端框架会对cookie名称进行规范化处理。当服务器将U+2000识别为空白字符时会自动移除,使cookie名变为__Host-name
。Django使用Python内置的.strip()
方法处理cookie键值,该方法会移除包括[133, 160, 5760, 8192–8202, 8232, 8233, 8239, 8287, 12288]在内的Unicode空白字符。
Safari处理方式不同:不支持多字节Unicode空白字符,但仍允许U+0085(NEL)和U+00A0(不换行空格)等单字节字符。
利用传统解析覆盖Cookie
除Unicode技巧外,传统cookie解析行为也可用于绕过前缀保护。若Cookie头以$Version=1
开头,Apache Tomcat等Java服务器会切换至传统解析模式,将单个cookie字符串解析为多个独立cookie:
|
|
此方式可绕过浏览器前缀检查,从子域或不安全源注入高权限cookie。
完整攻击场景
假设存在XSS漏洞且cookie值未转义直接反射到页面。应用使用__Host-
前缀cookie,正常情况下浏览器限制可防止不可信子域覆盖。但通过上述技术注入伪造cookie:
|
|
浏览器会同时发送原始cookie和攻击者控制的cookie:
|
|
后端解析时若存在同名cookie,Django等框架通常采用最后出现的值,导致攻击值优先。若应用未正确编码反射cookie值,将产生XSS漏洞;若cookie用于CSRF防护或会话识别,可能导致会话固定或权限提升。
Django官方回应指出该攻击依赖允许不可信子域cookie的场景,符合文档警告,因此不作为安全漏洞处理。
技术要点 浏览器与后端对同一cookie的解析差异可能悄无声息地破坏cookie保密性与完整性保证。本文作者已为Burp Suite创建轻量级自定义检测工具,可快速识别后端是否存在cookie前缀绕过漏洞。
本系列前文还演示了通过cookie sandwich技术窃取HttpOnly cookie的方法。