OWASP Top 10 不是漏洞一份静态的榜单,它更像是描述对Web应用安全风险的一次年度“体检报告”。2021年那版我印象很深,及解决方它把“访问控制失效”从第五名直接拉到了第一名,漏洞这背后反映的描述现实很残酷——很多漏洞并非因为技术多高深,而是及解决方开发者对“谁能做什么”这件事的边界没守住。
拿失效的漏洞访问控制来说,最典型的描述场景就是水平越权。你登录一个电商后台,及解决方把URL里的漏洞用户ID从100改成101,结果直接看到了别人的描述订单。这类问题在中小团队里尤其常见,及解决方因为大家默认“前端隐藏了按钮就等于后端做了限制”。漏洞但攻击者根本不看你的描述界面,他们直接发HTTP请求。及解决方解决方案其实不复杂:服务端对每个请求都要校验“当前用户是否拥有操作该资源的权限”,而不是信任前端传来的任何标识。另外,默认拒绝所有访问,只对明确允许的角色开放接口,能堵住大部分这类漏洞。
加密失败排第二,这名字改得比之前“敏感数据泄露”更精准。问题不在于“没加密”,而在于“用错了加密”。比如有些站点还在用SHA-1存密码,或者把信用卡号用AES-ECB模式加密——ECB模式会泄露数据模式,这在密码学上早就是反面教材了。我见过一个真实案例:某创业公司用Base64编码用户手机号就当作“加密”了,结果数据库泄露后所有号码直接明文可读。正确的做法分两层:传输层必须TLS 1.2以上,存储层对密码用bcrypt或argon2加盐哈希,对身份证号这类需要还原的数据用AES-GCM,并且密钥要放在HSM或云KMS里,别硬编码在代码中。
注入攻击跌到了第三,但别高兴太早——它只是变少了,没消失。SQL注入依然是黑产打数据库的首选路径,只是现在很多ORM框架帮忙挡了一部分。真正让我觉得头疼的是NoSQL注入和命令注入。比如MongoDB的查询操作符如果没做过滤,攻击者传入$gt或$ne就能绕过身份验证。这类问题没有一劳永逸的解法,唯一的出路是“参数化查询”这个原则要延伸到所有数据存储层,包括Redis脚本和系统命令调用。写代码时把用户输入永远当“数据”而不是“可执行代码”,这句话得刻在工位上。
安全配置错误和“不安全设计”这两个类别,其实暴露的是流程问题。前者比如默认账号没改、云存储桶权限设成公开、错误页面泄露了堆栈跟踪——这些不是技术难度问题,是惰性和疏忽。后者更麻烦,它指的是架构层面的缺陷,比如密码重置逻辑里“密保问题答案”本身可被猜测,或者多因素认证可以绕过。修复这类问题需要设计评审时引入威胁建模,而不是等代码写完再扫漏洞。我见过一个团队,因为设计时没考虑“用户注销后token仍有效”,导致账号被接管,后来不得不紧急下线全站重置会话——这种代价远比前期多想一步要高得多。
剩下五项——识别与认证失败、软件和数据完整性失效、安全日志与监控不足、服务端请求伪造(SSRF)——各有各的坑。SSRF在2021年上榜挺有意思,因为云原生架构让“从服务器发起请求”变得极其常见,攻击者利用这个功能去探测内网或元数据服务(比如AWS的169.254.169.254)。修这个漏洞的土办法是维护一个IP黑名单,但更稳的是做协议白名单,只允许访问特定域名或IP段,并且禁止重定向跟随。至于日志监控不足,说实话,很多小公司连集中式日志平台都没有,出了事只能翻单机文件——这已经不是技术问题,是生存问题了。
写到最后我得说句实话:OWASP Top 10再怎么更新,本质都是在提醒我们“安全没有银弹”。每修复一类漏洞,攻击者就会换一条路径。与其追求完美防御,不如把基础工作做扎实——权限校验、加密规范、参数化查询、日志留痕。这些事听起来不酷,但数据库被拖库时,能救你的就是这些枯燥的代码习惯。