OWASP TOP 10 2021核心风险解析与开发测试协同防御实践
1. 项目概述:为什么OWASP TOP 10是安全测试的“必修课”?
如果你是一名开发者,可能觉得写代码实现功能是第一要务,安全是安全团队的事。如果你是一名测试工程师,或许认为功能测试、性能测试已经够忙了,安全测试门槛太高。但现实是,无论是开发还是测试,如果对OWASP TOP 10没有一个清晰的认知,就像盖楼不知道地基的承重标准,写文章不检查错别字,项目上线后随时可能因为一个低级的安全漏洞而“翻车”。OWASP TOP 10,这份由开放Web应用安全项目(OWASP)定期发布的十大最严重Web应用安全风险清单,就是所有涉足软件开发和测试人员的“安全红宝书”。它不是什么高深莫测的黑客秘籍,而是一份基于全球大量真实漏洞数据统计出来的、最可能被攻击者利用的常见弱点清单。理解它,不是为了成为安全专家,而是为了在各自的岗位上筑起第一道,也是最重要的一道防线。对于开发而言,是在编码时就能规避的“安全编码规范”;对于测试而言,是设计测试用例时必须覆盖的“核心检查清单”。尤其在当前,随着“智能网联汽车道路测试与示范应用安全通行规范”等法规的出台,以及业务全面线上化、数据价值飙升的背景下,安全已从“附加题”变成了“必答题”。掌握OWASP TOP 10,就是拿到了解答这道必答题的基础公式。
2. OWASP TOP 10 2021版核心风险深度拆解
OWASP TOP 10并非一成不变,它随着攻击技术的演进和防御重点的转移而更新。我们以目前最新的2021版为基础进行拆解。与2017版相比,2021版更注重于不安全的设计、软件和数据的供应链安全等新维度。理解每一项风险,不能只记名字,更要明白其原理、危害和出现的典型场景。
2.1 A01:2021-失效的访问控制
这连续多次位居榜首的风险,说白了就是“该看的不让看,不该看的随便看”。访问控制决定了用户能否执行某个操作或访问某些数据。失效的访问控制意味着这些检查被绕过或缺失。
核心原理与场景: 想象一个电商网站,用户A只能查看和修改自己的订单(/orders/123)。如果系统没有在服务端对每次请求进行严格的权限校验,攻击者可能仅仅通过修改URL中的订单ID(如尝试访问/orders/124),就能越权看到用户B的订单详情。这就是典型的“水平越权”。更严重的“垂直越权”是,一个普通用户通过某种手段访问到了仅限管理员使用的后台功能页面(如/admin/user-list)。
开发视角的“坑”: 很多开发者在实现权限时,过于依赖前端控制。比如,在前端页面根据用户角色隐藏了“删除”按钮,但对应的API接口DELETE /api/article/{id}却没有做任何权限校验。攻击者完全可以通过工具直接调用这个API,导致任意文章被删除。另一个常见错误是使用可预测的标识符(如连续的数字ID)作为资源定位符,这为攻击者进行枚举攻击提供了便利。
测试验证要点: 测试时,不能只看UI。必须对每一个涉及身份和权限的API端点进行测试。使用不同的用户凭证(如普通用户Token、管理员Token、甚至无Token)去尝试访问本不应有权限的资源。自动化工具(如Burp Suite的Repeater模块)在这里是得力助手。同时,要检查是否存在不安全的直接对象引用(IDOR)。
注意:权限校验必须是服务端、每次请求都执行的行为。前端隐藏或禁用仅仅是用户体验优化,绝非安全措施。
2.2 A02:2021-加密机制失效
这一项涵盖了与加密相关的所有失败案例,不仅仅是传输过程,更包括存储和算法本身。其危害直接导致敏感数据(密码、个人信息、银行卡号、医疗记录)暴露。
核心原理与场景:
- 传输层不安全:网站仍使用HTTP而非HTTPS,或HTTPS配置存在严重缺陷(如支持弱加密套件、SSL证书过期)。这使得数据在传输过程中可能被窃听或篡改。公共Wi-Fi下登录一个HTTP网站,你的密码可能就是“明文广播”。
- 存储层不安全:用户密码明文存储在数据库中是灾难性的。即使数据库被拖库,攻击者也无法直接获取密码原文。但错误地使用弱哈希算法(如MD5、SHA1)或未加盐(Salt)的哈希,在彩虹表面前依然脆弱。
- 算法与密钥管理不当:使用自创的或已被证明不安全的加密算法(如DES),或将加密密钥硬编码在源代码、配置文件中并上传至GitHub。
开发视角的“坑”: 为了“省事”或“性能”,在内部系统通信时使用HTTP;在开发测试环境使用弱证书或自签名证书且不严格校验;对密码进行简单的MD5哈希后就觉得安全了;在代码里写死secret_key = "my_super_secret_key"。
测试验证要点:
- 传输安全:使用SSL Labs等在线工具扫描域名,检查SSL/TLS配置等级。用代理工具拦截请求,确认关键业务请求(登录、注册、支付)是否全部走HTTPS,且没有混合内容(HTTP资源)警告。
- 存储安全:这通常需要结合代码审计或与开发沟通确认。但可以通过“忘记密码”功能间接验证——如果系统能直接给你发回原密码,那一定是明文存储。
- 密钥检查:对前端代码(JS)进行简单的代码审查,看是否有硬编码的API密钥、加密密钥。
2.3 A03:2021-注入
这是最经典、危害极大的漏洞类型。当不可信的数据作为命令或查询的一部分被发送给解释器时,如果解释器将这些数据误解为代码而非数据,就会发生注入。最常见的是SQL注入,但也有OS命令注入、LDAP注入、NoSQL注入等。
核心原理与场景: 一个经典的SQL注入场景:登录逻辑的SQL语句是SELECT * FROM users WHERE username = ‘“ + userInput + ”’ AND password = ‘...‘。如果用户在用户名输入框输入admin‘ --,那么拼接后的SQL变成SELECT * FROM users WHERE username = ‘admin‘ --’ AND password = ‘...‘。--在SQL中是注释符,这意味着密码检查被完全绕过,攻击者可能以管理员身份登录。
开发视角的“坑”: 最大的坑就是使用字符串拼接来构造SQL语句、系统命令或任何解释性语言(如XPath、LDAP查询)的语句。另一个坑是过度信任ORM框架,认为用了ORM就绝对安全。实际上,如果使用不当(如用字符串拼接构造where条件),ORM同样可能产生注入。
测试验证要点:
- 手动探测:在任何用户输入点(表单、URL参数、HTTP头)尝试输入一些注入“探针”,如单引号
‘、双引号“、分号;、注释符--或#,观察应用返回的错误信息是否暴露数据库细节(这是“基于错误的注入”的迹象)。 - 工具扫描:使用SQLMap等自动化工具对可能存在数据库交互的参数进行深入检测。但要注意,工具不是万能的,且可能对生产环境造成影响,应在测试环境谨慎使用。
- 盲注测试:对于没有错误回显的应用,需要测试基于布尔或时间的盲注。例如,提交
1‘ AND 1=1 --和1‘ AND 1=2 --,观察页面响应内容或响应时间是否有差异。
2.4 A04:2021-不安全的设计
这是一个较新的类别,强调在软件设计阶段就存在的安全缺陷,而不是具体的实现bug。它关注的是“缺少或无效的安全控制设计”。例如,一个业务流程本身在设计上就允许高频次尝试密码而无需任何缓解措施(如验证码、锁定),这便是不安全的设计。
核心原理与场景:
- 业务流程缺陷:用户注册时,仅通过邮箱验证码即可完成,但系统未对同一IP或设备在短时间内发送验证码的次数做限制。攻击者可以利用此设计缺陷,对目标邮箱进行轰炸。
- 缺失安全功能:关键操作(如转账、修改密码)没有设计二次确认或交易密码环节。
- 默认不安全:系统默认配置是弱密码或开放所有权限。
开发与测试的协作: 这要求安全和隐私需求必须在需求分析和设计阶段就被明确提出。开发架构师需要将威胁建模纳入设计流程。测试人员则需要从业务逻辑层面进行“滥用案例”测试,思考“一个恶意用户会如何滥用这个正常功能?”。
测试验证要点: 测试需要超越单个功能点,关注业务流程链条。例如,测试一个电商的优惠券系统,不仅要测试能否正常领取和使用,还要测试:能否通过脚本批量领取?能否在支付环节通过并发请求重复使用同一张券?券的生成规则是否可预测(导致被枚举)?这些测试往往需要结合业务知识和对系统设计的深入理解。
2.5 A05:2021-安全配置错误
这是最“冤枉”的一类漏洞,因为应用本身代码可能没问题,但由于部署时的配置不当,导致安全门户大开。可以理解为买了一扇顶级防盗门,却忘了上锁,甚至把钥匙插在门上。
核心原理与场景:
- 云服务与容器配置:AWS S3存储桶配置为“公开可读”,导致大量公司敏感数据泄露;Docker容器以root权限运行;Kubernetes Dashboard未设置认证直接暴露在公网。
- 应用服务器/框架配置:保留默认的管理员账户和密码(如admin/admin);开启不必要的服务端口(如FTP、Telnet);错误配置的CORS策略,允许任意来源访问;暴露详细的错误信息(如Stack Trace)给普通用户。
- 依赖组件配置:使用的第三方库、框架(如Spring Boot Actuator, phpMyAdmin)未按安全指南进行加固配置。
开发与运维的协同: 开发有责任提供安全的默认配置和部署清单。运维和DevOps团队需要严格执行安全基线配置。基础设施即代码(IaC)和自动化配置管理工具(如Ansible, Terraform)能极大减少人为配置错误。
测试验证要点:
- 信息收集:使用Nmap等端口扫描工具,检查开放了哪些不必要的端口。使用DirBuster、GoBuster等目录扫描工具,寻找是否存在暴露的管理后台、备份文件(
.bak,.sql)、版本控制目录(.git/)。 - 默认凭证:尝试对发现的管理界面使用该软件常见的默认用户名/密码进行登录。
- 安全头检查:检查HTTP响应头,是否缺少关键的安全头,如
Content-Security-Policy(CSP)、X-Frame-Options、X-Content-Type-Options、Strict-Transport-Security(HSTS)。 - 错误信息:故意触发应用错误(如访问不存在的页面、输入非法参数),观察返回的错误信息是否包含服务器路径、数据库名称、代码片段等敏感信息。
2.6 A06:2021- vulnerable and Outdated Components(易受攻击和过时的组件)
现代软件开发严重依赖开源和第三方组件(库、框架、模块)。如果这些组件本身存在已知漏洞,那么你的应用就如同建立在布满裂缝的地基上。著名的Equifax数据泄露事件,根源就是一个未修复的Apache Struts 2漏洞。
核心原理与场景: 你的项目使用了一个开源的JSON解析库来处理用户输入。某天,该库被曝出一个高危的反序列化漏洞(CVE-XXXX-XXXX),攻击者可以构造恶意数据导致远程代码执行。如果你的应用没有及时更新这个库,那么即使你自己的代码写得再安全,整个应用也门户大开。
开发视角的“坑”:
- “能用就行”心态:从不更新
package.json、pom.xml、requirements.txt中的依赖版本。 - 间接依赖黑洞:只关注直接引入的组件,忽略了这些组件所依赖的深层嵌套组件(传递依赖),它们同样可能含有漏洞。
- 来源不可靠:从非官方、不受信任的源下载组件。
测试与治理要点:
- 软件成分分析(SCA):这是应对此风险的核心手段。使用SCA工具(如OWASP Dependency-Check, Snyk, WhiteSource)对项目代码库进行扫描,自动识别所有依赖组件及其版本,并与已知漏洞库(如NVD)进行比对,生成漏洞报告。
- 制定组件管理策略:团队应规定:禁止引入存在高危漏洞的组件;定期(如每季度)执行SCA扫描;对中低危漏洞进行风险评估;建立组件的审批和更新流程。
- 测试集成:将SCA工具集成到CI/CD流水线中,作为门禁。如果发现新的高危漏洞,可以自动失败构建,阻止含有已知漏洞的软件包被部署。
2.7 A07:2021-身份认证和会话管理失效
身份认证是确认“你是谁”,会话管理是维持“你已登录”的状态。这里的失效包括所有与登录、登出、密码管理、会话令牌管理相关的缺陷。
核心原理与场景:
- 弱密码策略:允许用户设置
123456、password等弱密码,或未强制要求密码复杂度、定期更换。 - 认证逻辑缺陷:登录接口在验证用户名和密码时,可能先查询用户是否存在,再验证密码。如果返回信息不同,攻击者可以利用这种差异枚举出系统中存在的有效用户名。
- 会话令牌问题:会话ID长度过短、可预测;退出登录后会话未在服务端失效;令牌未安全传输(未使用HTTPS);令牌未设置合理的过期时间。
开发视角的“坑”: 自己动手实现一套复杂的认证和会话管理逻辑,而不是使用久经考验的成熟框架(如Spring Security, Passport.js)。在URL中传递会话ID(导致日志泄露)。将敏感信息(如用户ID)存储在客户端的Cookie或LocalStorage中且未加密。
测试验证要点:
- 密码策略:尝试注册或修改密码,测试系统是否接受弱密码。
- 用户名枚举:在登录、注册、忘记密码等接口,尝试输入不同的用户名,观察返回的错误信息(如“用户名不存在”和“密码错误”是否不同)。
- 会话测试:
- 登录后,复制当前的会话Cookie或Token。
- 在另一个浏览器或隐私窗口中,不登录,直接访问需要认证的页面,并将复制的Cookie/Token替换进去,看是否能直接访问(测试会话固定/会话复用)。
- 在原浏览器点击“退出登录”后,再次使用刚才复制的Token访问,看是否仍然有效(测试会话销毁)。
- 多因素认证(MFA)绕过:如果系统有MFA,测试在验证了第一步密码后,能否跳过第二步直接访问内部页面。
2.8 A08:2021-软件和数据完整性故障
这项风险关注的是软件更新流程、CI/CD管道以及数据在传输和存储过程中的完整性是否被破坏。攻击者通过篡改更新包或构建过程,将恶意代码植入合法软件中。
核心原理与场景:
- 供应链攻击:攻击者入侵了某个开源库维护者的账户,或者劫持了该库的更新服务器(域名或仓库),发布一个带有后门的版本。下游所有引用了这个库的应用在更新时,就会自动引入恶意代码。著名的“太阳风”(SolarWinds)事件就是典型案例。
- 不安全的CI/CD:构建服务器的访问控制不严,或者构建脚本从不可信的源拉取依赖,导致构建产物被污染。
- 数据完整性缺失:从客户端上传的插件、配置文件、代码,服务端未经验证其完整性和真实性就直接执行或使用。
开发与运维的协同:
- 使用依赖签名和校验:对于关键组件,应从官方渠道获取,并验证其PGP签名或哈希值(如SHA256)。
- 加固CI/CD管道:对构建环境进行严格隔离和访问控制;使用可信的镜像源;对构建产物进行安全扫描。
- 实施代码签名:对于发布的客户端软件或更新包,使用代码签名证书进行签名,客户端验证签名后再安装。
测试验证要点: 测试人员很难直接测试这种风险,更多是流程审计。但可以关注:
- 应用的自动更新机制是否使用了HTTPS和签名验证?
- 公司内部是否有对第三方组件来源和完整性的审查流程?
- CI/CD系统的访问日志是否被监控?是否有异常构建活动的告警?
2.9 A09:2021-安全日志与监控失效
这一项关乎事后的“侦查”和“响应”能力。如果系统被攻击但没有记录足够的日志,或者有日志却无人监控分析,那么攻击者就可以长期潜伏、反复入侵而不被发现。这相当于家里被盗了,但监控摄像头没开,或者录像坏了。
核心原理与场景:
- 日志记录不足:只记录了“info”级别的常规日志,没有记录登录失败、权限校验失败、关键数据访问、异常输入等安全事件。
- 日志格式不统一:不同服务、不同模块的日志格式五花八门,难以进行集中分析和关联。
- 日志未保护:日志文件本身包含敏感信息(如密码、密钥),并且权限设置不当,导致低权限用户或攻击者可以读取。
- 缺乏实时监控与告警:没有对日志进行实时分析,无法在发生暴力破解、爬虫扫描、数据泄露时及时发出告警。
开发与运维的协同: 开发需要在代码中关键位置(尤其是认证、授权、核心业务操作、异常处理)植入结构化的日志记录,包含足够上下文(用户ID、IP、时间戳、操作对象、结果)。运维需要搭建集中式的日志管理平台(如ELK Stack, Loki),并配置监控规则和告警(如使用Prometheus + Alertmanager)。
测试验证要点:
- 验证日志内容:执行一些敏感操作(如登录失败、越权访问尝试),然后检查对应的应用日志或审计日志中是否留下了清晰、可追溯的记录。记录中是否包含关键要素(Who, When, Where, What)?
- 测试日志注入:尝试在用户输入中插入换行符、特殊字符,看是否会破坏日志格式或注入虚假的日志条目。
- 审查监控覆盖:了解运维团队对哪些安全事件配置了监控和告警。可以模拟一次低频的暴力破解攻击,看是否会触发告警。
2.10 A10:2021-服务器端请求伪造
SSRF是一种由攻击者构造请求,诱使服务器向内部或外部系统发起非预期请求的攻击。由于请求是由服务器发出的,攻击者可能借此访问到服务器本身才能访问的内部系统(如元数据服务、内部管理后台),或者绕过防火墙规则。
核心原理与场景: 一个常见的场景是“网页转码”或“图片抓取”功能。用户提供一个URL,服务器去抓取那个URL的内容并返回。如果这个功能没有对用户输入的URL进行严格过滤,攻击者可以输入http://169.254.169.254/latest/meta-data/(AWS云服务器的元数据服务内网地址)。服务器就会向这个内部地址发起请求,并将敏感的元数据(可能包含临时访问凭证)返回给攻击者。
开发视角的“坑”: 盲目信任用户输入的URL,仅在前端做简单的格式校验,或者只在服务端用正则判断是否以http://开头,然后就直接用curl、requests等库去获取。没有对目标地址的IP、域名、协议、端口进行白名单限制。
测试验证要点:
- 寻找SSRF触发点:寻找任何允许用户输入URL、IP或主机名的功能点,如图片/文件上传(远程URL)、数据导入、Webhook回调地址设置、站内链接预览等。
- 使用测试Payload:
- 尝试访问内部服务:
http://127.0.0.1:8080/admin,http://localhost,http://[::1]:3306(MySQL)。 - 尝试访问云元数据:
http://169.254.169.254/(AWS, GCP),http://100.100.100.200/(阿里云)。 - 使用DNS重绑定技术,绕过基于域名的初步过滤。
- 尝试访问内部服务:
- 观察差异:根据服务器的响应时间、返回内容、错误信息来判断请求是否成功发往了内部地址。有时服务器可能只返回一个“处理失败”的通用提示,但通过响应时间的显著延长,可以推断它可能尝试连接了一个不存在的内部端口(超时)。
3. 从理论到实践:开发与测试的协同防御体系
了解了十大风险,关键在于如何将其融入日常开发与测试流程,形成“安全左移”的协同防御体系。这不仅仅是安全团队的事,而是每个研发环节参与者的责任。
3.1 开发侧:将安全编码融入肌肉记忆
对于开发者,安全不是最后一个环节的“安全检查”,而是编码时的一种思维方式。
1. 安全需求与设计阶段: 在需求评审和系统设计时,主动提问:“这个功能涉及哪些敏感数据?(A02)”“用户权限模型是怎样的?如何防止越权?(A01)”“这个外部接口调用,会不会有SSRF风险?(A10)”。参与或发起简单的威胁建模,识别潜在的攻击面。
2. 编码实现阶段:
- 访问控制(A01):在任何数据访问和业务操作前,明确进行权限校验。使用统一的权限检查框架或中间件,避免散落在业务代码各处。对资源ID使用不可预测的令牌(如UUID)替代自增ID。
- 注入防御(A03):绝对禁止字符串拼接SQL。使用参数化查询(Prepared Statements)或ORM框架的安全方法。对于命令执行,严格限制参数,使用白名单校验。
- 输入输出处理:对所有用户输入进行严格的校验和过滤(白名单优于黑名单)。对输出到HTML页面的内容进行恰当的编码(防御XSS,虽然XSS在TOP 10 2021中未单独列出,但仍是重大风险),使用安全的API(如
textContent替代innerHTML)。 - 依赖管理(A06):使用包管理器,定期(可通过CI自动化)运行
npm audit、pip-audit、OWASP Dependency-Check等命令扫描漏洞。及时更新依赖,特别是含有高危漏洞的版本。 - 错误处理:定义统一的、不泄露内部细节的错误处理机制。向用户返回友好的通用错误信息,而将详细错误记录在安全的服务器日志(A09)中。
- 使用安全库和框架:优先使用具有良好安全声誉的框架(如Spring Security, Helmet.js),它们通常内置了针对CSRF、XSS、点击劫持等常见攻击的防护。
3. 代码审查阶段: 将安全作为代码审查(Code Review)的必查项。审查者除了看代码逻辑和风格,更要关注是否存在上述的安全反模式。可以建立团队的安全编码规范清单,在Review时对照检查。
3.2 测试侧:构建多层次的安全测试能力
测试人员是安全防线的关键验证者,需要从功能测试思维升级到攻击者思维。
1. 安全测试左移:SAST与SCA
- 静态应用安全测试(SAST):在代码编写阶段或提交后,使用SAST工具(如SonarQube, Fortify, Checkmarx)对源代码进行扫描,发现潜在的编码漏洞(如注入、硬编码密码)。这类工具可以集成到IDE或CI流水线,给开发者即时反馈。
- 软件成分分析(SCA):如前所述,在CI流水线中集成SCA工具,自动化扫描第三方依赖漏洞,阻断含有高危漏洞的构建产物进入下一阶段。
2. 动态安全测试与渗透测试
- 动态应用安全测试(DAST):对正在运行的应用(通常是测试环境)进行黑盒测试,模拟外部攻击者的行为,发送恶意请求来发现运行时漏洞(如A01, A03, A05, A07)。工具如OWASP ZAP、Burp Suite(商业版)自动化程度高,是测试人员的好帮手。
- 交互式应用安全测试(IAST):结合了SAST和DAST的优点,通过在应用运行时插桩来监控漏洞,能更准确地定位漏洞所在的代码行,误报率较低。
- 手动渗透测试:自动化工具无法覆盖所有场景,尤其是业务逻辑漏洞(A01, A04)。测试人员需要根据对业务的理解,手动设计测试用例。例如,测试一个拍卖系统,除了出价功能本身,还要测试:能否在最后时刻通过并发请求覆盖他人的出价?能否修改出价金额为负数?
3. 制定安全测试用例库围绕OWASP TOP 10的每一项,为负责的系统制定具体的安全测试用例。例如:
- A01测试用例:用户A登录后,尝试直接访问用户B的资源ID(订单、个人资料)。尝试访问仅管理员可见的URL或API。
- A03测试用例:在所有搜索框、表单输入框尝试SQL注入和XSS payload。测试文件上传功能是否可能上传恶意脚本。
- A07测试用例:测试弱密码规则、登录失败锁定机制、会话超时时间、退出登录后会话是否失效。
4. 模糊测试与漏洞奖励对于核心或高风险模块,可以采用模糊测试(Fuzzing),向系统输入大量随机、畸形数据,观察其是否崩溃或行为异常,以发现潜在的边界和安全问题。对于拥有大量用户和敏感数据的公司,可以考虑建立漏洞奖励计划,借助外部白帽黑客的力量发现更深层次的问题。
4. 实战演练:一个简单的Web应用安全测试Checklist
理论需要结合实践。下面我以一个假设的“用户个人中心与文章发布系统”为例,整理一份开发自测和测试人员可用的简易安全检查清单。你可以根据这个清单,为你自己的项目量身定制。
环境与配置安全(A05, A09)
- [ ] 生产环境是否关闭了调试模式和详细的错误回显?
- [ ] 是否使用了HTTPS,且SSL配置符合安全标准(如A+评级)?
- [ ] 服务器是否删除了默认页面、示例程序和无关的文档?
- [ ] 是否对敏感目录(如
/admin,/backup,/phpmyadmin)设置了访问限制? - [ ] 应用日志是否记录了关键安全事件(登录成功/失败、权限拒绝、数据删除)?
- [ ] 日志中是否避免了记录敏感信息(如完整信用卡号、密码)?
身份认证与会话(A07)
- [ ] 登录功能是否有防止暴力破解的机制(验证码、失败锁定)?
- [ ] 密码策略是否强制要求一定的长度和复杂度?
- [ ] “记住我”功能生成的令牌是否安全(随机、长、可撤销)?
- [ ] 会话Cookie是否设置了
HttpOnly、Secure和SameSite属性? - [ ] 退出登录后,服务端是否立即销毁了会话?
- [ ] 修改密码后,是否使其他设备的现有会话失效?
访问控制(A01)
- [ ] 非登录用户是否绝对无法访问任何需要认证的页面或API?
- [ ] 普通用户是否无法通过修改URL参数访问其他用户的个人数据(水平越权)?
- [ ] 普通用户是否无法访问管理员专属的功能或API(垂直越权)?
- [ ] 所有服务端API是否在业务逻辑层都进行了权限校验?(不仅仅是前端隐藏按钮)
输入验证与注入(A03, A10)
- [ ] 所有用户输入(表单、URL参数、HTTP头)在服务端是否都进行了校验或过滤?
- [ ] 数据库查询是否全部使用参数化查询或安全的ORM方法?
- [ ] 输出到HTML页面的用户数据是否进行了正确的编码(防御XSS)?
- [ ] 文件上传功能是否限制了文件类型、检查了文件内容、将上传文件存储在Web根目录之外?
- [ ] 是否存在根据用户输入URL获取资源的功能?如有,是否对目标URL的协议、域名、IP进行了严格的白名单限制?(防御SSRF)
数据安全(A02)
- [ ] 用户密码是否使用强哈希算法(如Argon2, bcrypt, PBKDF2)并加盐存储?
- [ ] 敏感信息(如身份证号、手机号)在数据库中是否加密存储?
- [ ] 在日志或前端展示时,敏感信息是否进行了脱敏处理(如显示为
138****1234)?
依赖与供应链(A06, A08)
- [ ] 是否定期(如每周/每月)使用SCA工具扫描项目依赖的漏洞?
- [ ] 是否有一个流程来评估和修复扫描出的中高危漏洞?
- [ ] 项目的CI/CD管道是否安全?构建服务器的访问是否受控?
业务逻辑安全(A04)
- [ ] 关键操作(如转账、删除账号)是否有二次确认机制?
- [ ] 业务接口是否可能被滥用?例如,领取优惠券的接口是否没有频率限制?
- [ ] 工作流程是否存在绕过可能?例如,能否不完成前一步就直接访问后一步?
这份清单只是一个起点。真正的安全是一个持续的过程,需要开发、测试、运维乃至产品经理的共同参与和努力。将安全意识和实践嵌入到软件开发生命周期的每一个环节,才能构建出真正值得用户信赖的应用。
