第 11 篇:横向越权(IDOR)——改个数字看别人的数据
IDOR 是最不起眼也最常见的漏洞:接口按 id 取资源,却没检查这个 id 是不是当前用户的。把 URL 里的 1001 改成 1002,就看到了别人的订单。这一篇用十几行说清它的机制,以及为什么真正的修复不是’把 id 换成猜不到的 UUID’,而是’把归属校验写进每一次数据访问’。
IDOR 是最不起眼也最常见的漏洞:接口按 id 取资源,却没检查这个 id 是不是当前用户的。把 URL 里的 1001 改成 1002,就看到了别人的订单。这一篇用十几行说清它的机制,以及为什么真正的修复不是’把 id 换成猜不到的 UUID’,而是’把归属校验写进每一次数据访问’。
纵向越权是普通用户够到了管理员的能力。它最常见的成因只有一句话:鉴权做在了前端(藏起按钮、隐藏菜单),而后端端点谁都能调。这一篇证明「藏按钮 ≠ 鉴权」,说清鉴权该放在哪一层、为什么必须默认拒绝,以及为什么客户端上的任何检查都只是体验、不是安全。
W4 开篇,先讲同源策略到底保护什么。CSRF 钻的正是它的一个空子:浏览器向某站发请求会自动带上该站的 cookie,不管请求从哪个页面发起。于是’只认 cookie’的状态改变端点能被任意站点伪造。这一篇起一个真实的 HTTP 服务器,用标准库的 http.cookiejar 当受害者的浏览器——cookie 由它按浏览器规则自动附带,于是“跨站提交就把邮箱改掉了”这件事是真的跑出来的。再说清 CSRF 令牌为什么有效、以及 SameSite 把这道防线前移到了浏览器。
CORS 不是’防护’,是同源策略的一份放行名单——它决定哪些外站的 JS 能读你的响应。配错了,等于把上一篇讲的那道’拦读内容’的墙拆掉。这一篇先用一个真实的服务器复现最常见的致命配置:把请求的 Origin 原样反射回去 + 允许携带凭据;再说清为什么真正的洞几乎总是’动态反射 Origin’而不是一个星号;最后把四种常见的’支持所有子域’写法跑一遍,看哪几种会放进攻击者自己能注册的域名。
W4 收尾,讲两个跨窗口的信任问题。Clickjacking:攻击者用透明 iframe 把你的页面叠在他的页面上,用户以为点的是这边、其实点的是那边——防线是告诉浏览器’我不许被别人嵌’。postMessage:跨窗口通信时接收方不校验来源,就把任何页面发来的消息当可信处理。两段 demo 都得在浏览器里跑,因为这两件事的判定权都在浏览器手里:能不能被 iframe、消息的 origin 是什么,都是它说了算。
Heartbleed 的核心只有一句话:它信任了对方声称的长度。你发 5 字节说自己是 25 字节,服务器就回给你 25 字节——多出来的 20 字节是隔壁内存里别人的数据。这一篇用最小骨架复现这个机制,说明为什么’读’也能是重大漏洞,以及为什么’凡是来自对方的长度/大小/偏移都要用实际数据核验’是一条通用规则。
很多漏洞不在’解析错了’,而在’两个解析器把同一段字节解析成了不同的东西’。当你的前端代理和后端服务器对同一个请求的理解不一致,两者理解的分歧处就能塞进一个走私的请求。这一篇用可运行的例子复现 HTTP 请求走私的核心分歧,并把它上升为一条通用教训:任何’多个组件各自解析同一份输入’的地方,都要保证它们理解一致。
W6 开篇。你的代码里,自己写的可能只占几个百分点,其余全是依赖——而每一个依赖都是一条你没审过的代码进入你系统的通道。这一篇讲攻击者往这条通道里塞东西的几条路:抢注、依赖混淆、账号接管、维护者移交。其中依赖混淆用真实的 pip 复现:两个源里放同名包,pip 自己跳过内网源选走了公共源那个高版本。
上一篇防的是’装进来的依赖有毒’。这一篇往上游一步:连你自己的代码,从源码到用户手里的产物之间,还隔着构建和 CI 这一段——而这一段本身就是攻击面。SolarWinds 的教训是’源码干净、构建被改、产物带毒’;Codecov 的教训是’一个 CI 脚本卷走了环境里的所有密钥’。核心两句:验证要验最终产物、CI 令牌要最小权限。
W7 开篇。前面十九篇多在讲代码里的漏洞,这一篇讲一类根本不用写错代码的漏洞:你什么都没做错,只是用了默认配置——而默认配置是为’开箱能跑’优化的,不是为’安全’优化的。调试模式、默认口令、目录列举、暴露的管理端口,逐项看它们各自泄露了什么,以及为什么’默认拒绝’要贯彻到配置层。