客户端 javascript cookie引用漏洞修复
上周五晚上十一点,客户我盯着监控面板上突然飙升的端j洞修401错误,差点把咖啡泼在键盘上。引用漏攻击者利用的客户正是我们前端代码里一个看起来人畜无害的cookie引用——`document.cookie.split(';')[0]`。这个写法在无数教程里出现过,端j洞修却让攻击者通过构造恶意cookie头,引用漏直接绕过了我们刚刚上线的客户权限校验逻辑。
问题出在哪?端j洞修`split(';')[0]`想当然地认为第一个分号前就是目标cookie。但浏览器对cookie的引用漏解析远比这复杂——同名cookie可能出现在不同路径,`HttpOnly`标记可能让某些值读不到,客户更别提某些浏览器对cookie顺序的端j洞修处理并不严格。攻击者只要在请求头里塞一个伪造的引用漏`session=admin; session=user`,某些解析逻辑就会取到第一个值,客户权限直接提级。端j洞修
修复不能靠补丁式地改一行索引。引用漏我见过太多团队把`[0]`改成`[1]`就以为万事大吉,结果换个浏览器又炸了。真正的解法是建立一个统一的cookie解析工具函数,用正则精确匹配目标key,而不是依赖位置。比如:
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^|; )' + name + '=([^;]*)'));
return match ? decodeURIComponent(match[2]) : null;
}
这个写法强制要求cookie名前后有明确的边界符,杜绝了位置依赖。
但光改解析还不够。你得回头审视每个引用cookie的地方——是不是有直接拼接进DOM的?是不是有塞进URL参数的?我们有个搜索页面曾经把cookie值直接拼进`window.location`,攻击者注入`javascript:alert(1)`就能执行脚本。这种引用漏洞比解析漏洞更隐蔽,因为代码审查时很难注意到赋值语句右侧的变量来源。
我的习惯是给所有cookie读取加一层白名单校验。不是每个cookie都需要被前端读取,像`sessionid`这种敏感值,后端应该在`Set-Cookie`时加上`HttpOnly`标记,前端根本不该碰。真正需要读的,比如用户偏好设置,值必须符合预设格式——是JSON就`JSON.parse`,是数字就`parseInt`后检查`isNaN`。这层校验放在工具函数里,所有调用方强制走这个入口,比在几十个页面里逐个加判断靠谱得多。
还有个小坑你可能想不到:`document.cookie`返回的字符串在移动端WebView里偶尔会带上前导空格。我调试过一个安卓机型,cookie值怎么都读不对,最后打印出来才发现开头多了个看不见的`\uFEFF`字符。所以解析函数里最好先`trim()`一下,别嫌多余。
修复上线后我盯着监控看了整晚,401错误率降到了零。但这事没完——我拉了个仓库扫描脚本,把所有直接操作`document.cookie`的代码全部列出来,逐条确认是否走了统一工具函数。目前还剩十几个历史遗留的散装写法,计划下个迭代全部清掉。安全这东西,你留一个口子,就等于没堵。
