当前位置:首页 > 知识

cookies漏洞

去年夏天,我帮一个朋友查他网站被入侵的事。攻击者没碰数据库,没上传webshell,只改了一个Cookie字段,就把管理员权限拿到了。整个过程干净得像进自己家。

问题出在他把用户角色直接写进了Cookie。类似这样:role=user。攻击者用浏览器插件把值改成role=admin,刷新页面,后台管理菜单就出来了。没有二次校验,没有签名,服务端读到这个Cookie就信了。

这不是什么高深漏洞。它有个名字叫Cookie篡改,原理简单到离谱——Cookie存在客户端,用户想怎么改就怎么改。你把信任放在用户能控制的地方,就等于把钥匙藏在门垫下面,还贴了张纸条写“钥匙在此”。

明文存储的代价

很多开发者知道Cookie不安全,但“不安全”三个字太抽象。具体点说:Chrome的开发者工具里,Application面板打开,Cookie一览无余。改值、加字段、删属性,三秒钟的事。Firefox更直接,存储面板双击就能编辑。

我见过一个电商站,把购物车总价放在Cookie里传给支付网关。用户把total=299改成total=0.01,支付接口照单全收。后来他们加了服务端重算,但那是被薅了两个月之后的事。

还有个更隐蔽的案例。某SaaS平台用Cookie存tenant_id来区分租户。一个用户改了tenant_id,直接看到了另一家公司的项目数据。这不是越权漏洞,这是架构缺陷——多租户隔离靠客户端传参,等于没隔离。

签名和加密,两码事

有人说,那我给Cookie加个签名不就行了。对,但得看怎么签。

HMAC签名能防篡改,前提是密钥不泄露、算法不拉胯。我审计过一个系统,签名用的是MD5(secret + value),secret硬编码在前端JS里。这签名跟纸糊的没区别。

加密呢?AES加密Cookie内容,用户看不懂明文,但重放攻击照样成立。攻击者不需要知道里面是什么,原样复制粘贴到另一个账户的请求里,服务端解密后发现合法,照样放行。加密解决的是机密性,不是完整性,更不是身份绑定。

真正靠谱的做法是服务端会话。Cookie里只放一个随机session ID,所有状态存服务端。用户改ID?改完就是个无效会话,直接踢到登录页。简单、粗暴、有效。

HttpOnly和Secure只是底线

设置HttpOnly能防XSS偷Cookie,设置Secure能防中间人嗅探。这两个属性是基本操作,但很多人配了就觉得万事大吉。

HttpOnly防不住CSRF。攻击者不需要读Cookie,他只需要让受害者的浏览器带着Cookie发请求。银行转账接口如果只靠Cookie鉴权,一个img标签就能触发转账。

SameSite属性现在浏览器默认是Lax,能挡掉大部分跨站POST。但有些老系统还在用None,还带着Secure,看起来合规,实际上CSRF大门敞开。

我自己的习惯:凡是涉及权限、金额、租户隔离的字段,一律不进Cookie。会话ID用__Host-前缀,强制Secure、Path=/、无Domain。服务端每次请求都校验session有效性,该过期过期,该轮转轮转。

Cookie本身不是漏洞。把不该放的东西放进去,还不加验证,才是。

分享到: