ASVS
格式说明:✅ 必须做 = 正确做法 | ❌ 禁止做 = 错误做法/反模式 | 🛡️ 防御 = 对抗的攻击类型
V1 编码与过滤
V1.1 输入解码与输出编码
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V1.1.1 | 输入只解码/反转义一次,且在验证/过滤之前完成 | 先验证再解码;多次解码(双重URL解码等) | 双重编码绕过 |
| V1.1.2 | 输出编码在交给解释器的最后一步执行 | 提前编码后又拼接未编码内容 | 注入攻击通用防线 |
V1.2 注入防护
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V1.2.1 | 按上下文对输出编码:HTML元素用HTML实体编码、HTML属性加引号并编码、CSS值编码、HTTP头字段编码 | 所有场景用同一种编码;不区分HTML元素/属性/注释/CSS上下文 | XSS |
| V1.2.2 | 动态构建URL时:查询参数用encodeURIComponent()、路径用URL编码。白名单协议仅允许http:/https: | 拼接用户输入构建URL不编码;允许javascript:或data:协议 | XSS、开放重定向 |
| V1.2.3 | 动态生成JS/JSON时使用JS专用编码(如JSON.stringify()后嵌入<script>时转义</) | 直接把用户输入拼进<script>标签或JSON字符串 | JS/JSON注入 |
| V1.2.4 | 数据库查询必须用参数化查询/预编译语句/ORM,存储过程内部也一样 | 字符串拼接SQL语句;存储过程内拼接动态SQL | SQL注入 |
| V1.2.5 | 系统命令调用用参数数组传参(如execFile而非exec),或做命令行编码 | os.system("ping " + userInput)、Runtime.exec(cmd + userInput) | OS命令注入 |
| V1.2.6 | LDAP查询使用转义函数处理(、)、*、\、NUL等特殊字符 | 直接拼接用户输入到LDAP过滤器 | LDAP注入 |
| V1.2.7 | XPath查询使用参数化接口或预编译表达式 | 字符串拼接XPath表达式 | XPath注入 |
| V1.2.8 | LaTeX配置:禁用--shell-escape,使用命令白名单限制可执行的LaTeX命令 | 开启--shell-escape;允许用户输入任意LaTeX命令 | LaTeX注入→RCE |
| V1.2.9 | 用户输入拼入正则表达式前,用转义函数处理.*+?^${}()\|[]等元字符 | 直接把用户输入作为正则pattern | ReDoS、正则注入 |
| V1.2.10 | CSV导出遵循RFC 4180转义规则;字段首字符为= + - @ \t \0时加单引号前缀 | 直接输出用户数据到CSV/Excel不做处理 | CSV注入、公式注入 |
V1.3 过滤
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V1.3.1 | 富文本(WYSIWYG编辑器)输入使用成熟的HTML过滤库(如DOMPurify、Bleach、OWASP Java HTML Sanitizer) | 自己写正则过滤HTML标签;黑名单方式过滤 | 存储型XSS |
| V1.3.2 | 禁用eval()及类似动态执行(SpEL、OGNL)。万不得已时,对输入做严格白名单过滤 | eval(userInput)、new Function(userInput)、SpEL解析用户表达式 | 代码注入、RCE |
| V1.3.3 | 数据进入危险上下文前,白名单过滤安全字符 + 截断超长输入 | 信任前端已做过滤;仅靠黑名单移除危险字符 | 通用注入 |
| V1.3.4 | 用户上传SVG时,白名单仅允许绘图标签(<svg>, <rect>, <circle>等),移除<script>、<foreignObject>、事件属性 | 允许SVG中包含JS脚本和任意HTML元素 | XSS(SVG载体) |
| V1.3.5 | 用户提供的Markdown/CSS/XSL/BBCode等模板语言内容做过滤或禁用脚本能力 | 直接渲染用户Markdown中的<script>;允许CSS expression() | XSS、CSS注入 |
| V1.3.6 | 外发请求URL做白名单校验(协议+域名+端口+路径),移除危险字符 | 允许用户指定任意URL让服务端去请求 | SSRF |
| V1.3.7 | 禁止用户输入构建服务端模板。若无法避免,严格白名单/沙箱隔离 | render_template_string(userInput)(Flask)、Jinja2拼接用户输入 | SSTI模板注入→RCE |
| V1.3.8 | JNDI查询前过滤输入,禁用远程类加载(com.sun.jndi.ldap.object.trustURLCodebase=false) | 将用户输入直接传入InitialContext.lookup() | JNDI注入(Log4Shell类) |
| V1.3.9 | 写入Memcache前过滤\r\n等分隔符 | 直接拼接用户输入到Memcache命令 | Memcache注入 |
| V1.3.10 | 使用格式字符串前过滤或硬编码模板(如C的printf、Python的format) | printf(userInput)、userInput.format(...) | 格式字符串漏洞 |
| V1.3.11 | 用户输入发送到邮件系统前过滤\r\n、SMTP命令字符 | 直接把用户输入拼到邮件头(To/CC/Subject) | SMTP/IMAP注入 |
| V1.3.12 | 正则表达式避免嵌套量词(如(a+)+),不可信输入先过滤再匹配,设置匹配超时 | 用用户输入直接构建复杂正则 | ReDoS |
V1.4 内存安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V1.4.1 | 使用安全字符串函数(strncpy替代strcpy),或使用内存安全语言(Rust/Go) | strcpy、strcat、sprintf无长度限制 | 栈/堆/缓冲区溢出 |
| V1.4.2 | 整数运算前做范围检查和符号校验,使用安全整数库 | 直接用用户输入做malloc(size)或数组索引不检查 | 整数溢出 |
| V1.4.3 | 释放内存后立即置指针为NULL;使用智能指针/RAII | free(ptr)后继续使用ptr;重复free | UAF、悬空指针 |
V1.5 反序列化与解析安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V1.5.1 | XML解析器配置:禁用DTD、禁用外部实体(setFeature("disallow-doctype-decl", true)) | 使用默认XML解析器配置处理用户XML | XXE |
| V1.5.2 | 反序列化使用类型白名单,禁用ObjectInputStream默认行为,改用JSON等安全格式 | ObjectInputStream.readObject()直接反序列化不可信数据;使用pickle.loads()处理用户输入 | 反序列化RCE |
| V1.5.3 | 同一数据类型的不同解析器(JSON/XML/URL)统一字符编码和解析行为 | JSON用一个库、XML用另一个库,编码处理不一致 | 解析差异利用、RFI/SSRF |
V2 业务逻辑
V2.1 输入验证文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V2.1.1 | 文档化每个输入字段的验证规则(格式、长度、范围、类型) | 无文档说明,输入规则全靠代码自行理解 | 验证遗漏 |
| V2.1.2 | 文档化组合字段校验逻辑(如省份+邮编匹配、开始日期<结束日期) | 只验证单个字段,不验证关联逻辑 | 逻辑绕过 |
| V2.1.3 | 文档化业务限制(每用户限额、全局限额、操作频率) | 限制规则只存在于开发者脑中 | 业务逻辑滥用 |
V2.2 输入验证实施
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V2.2.1 | 白名单正向验证:校验允许的值、模式、范围、类型 | 仅用黑名单过滤已知坏字符;不验证业务范围 | 各类注入、逻辑绕过 |
| V2.2.2 | 输入验证在后端可信层执行。前端验证仅为用户体验 | 仅前端JS验证,后端不校验 | 前端绕过 |
| V2.2.3 | 关联字段做组合校验(金额+币种匹配、地址各字段一致) | 各字段独立验证不检查逻辑一致性 | 数据不一致利用 |
V2.3 业务逻辑流程
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V2.3.1 | 多步骤流程在后端强制步骤顺序(状态机),每步校验上一步完成 | 允许用户直接跳到最后一步(如跳过支付直接确认订单) | 流程跳步 |
| V2.3.2 | 按文档化的规则实施业务限制(金额上限、操作次数等) | 文档写了限制但代码没实现 | 业务逻辑缺陷 |
| V2.3.3 | 业务操作使用数据库事务,失败时完整回滚 | 多步操作中途失败留下不一致数据 | 数据不一致 |
| V2.3.4 | 有限资源(库存、座位、时段)使用悲观锁/乐观锁防并发超卖 | 先查再扣不加锁 | 超卖、重复预订 |
| V2.3.5 | 高价值操作(大额转账、合同审批)要求多人审批 | 单人即可完成高风险操作 | 未授权/误操作 |
V2.4 反自动化
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V2.4.1 | 实施速率限制、验证码、IP限流等反自动化控制 | 接口无任何调用频率限制 | 撞库、数据爬取、DoS |
| V2.4.2 | 关键流程校验操作时间是否符合人类速度(如注册填表<2秒则拒绝) | 允许毫秒级完成需要分钟级的操作 | 自动化攻击 |
V3 Web 前端安全
V3.1 浏览器安全文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.1.1 | 文档化应用要求浏览器支持的安全特性(HTTPS/HSTS/CSP),并定义不支持时的降级行为(警告/拒绝) | 不声明浏览器安全要求,兼容所有老旧浏览器不做任何提示 | 降级攻击 |
V3.2 浏览器安全控制
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.2.1 | 通过Sec-Fetch-*头校验请求上下文;对API响应/文件下载设Content-Disposition: attachment或CSP sandbox | API端点和页面端点不区分,直接返回HTML可渲染 | MIME混淆、直链XSS |
| V3.2.2 | 显示用户文本用textContent/createTextNode | innerHTML = userInput、document.write(userInput) | DOM XSS |
| V3.2.3 | JS变量用let/const声明;不在document上存全局变量;做命名空间隔离 | document.xxx = data;隐式全局变量 | DOM Clobbering |
V3.3 Cookie 安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.3.1 | 所有Cookie加Secure标记。Cookie名用__Host-或__Secure-前缀 | Cookie不设Secure;通过HTTP明文传输 | Cookie劫持 |
| V3.3.2 | 按用途设置SameSite:认证Cookie用Strict或Lax;跨站需要的用None+Secure | 不设SameSite,使用浏览器默认行为 | CSRF |
| V3.3.3 | Cookie名用__Host-前缀(限定当前域、HTTPS、路径/) | 需要跨子域共享时才用__Secure-替代 | Cookie注入/覆盖 |
| V3.3.4 | 会话令牌Cookie必须设HttpOnly;敏感值仅通过Set-Cookie头传递 | 会话令牌可被JS读取(document.cookie) | XSS窃取会话 |
| V3.3.5 | 单个Cookie的名+值总长度≤4096字节 | 写入超大Cookie导致后续请求被浏览器丢弃 | Cookie炸弹DoS |
V3.4 HTTP 安全头
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.4.1 | 所有响应加Strict-Transport-Security: max-age=31536000; includeSubDomains | 不设HSTS;max-age过短 | SSL剥离 |
| V3.4.2 | CORS:Access-Control-Allow-Origin用固定值或白名单校验。通配符*时确保响应无敏感数据 | 直接回显请求的Origin头;Access-Control-Allow-Origin: *配合Allow-Credentials: true | 跨域数据窃取 |
| V3.4.3 | 设置CSP头:至少object-src 'none'; base-uri 'none'。L3要求每个响应使用nonce/hash | Content-Security-Policy: *;不设CSP | XSS |
| V3.4.4 | 所有响应加X-Content-Type-Options: nosniff | 不设此头,浏览器可能把文本猜测为HTML执行 | MIME嗅探XSS |
| V3.4.5 | 设Referrer-Policy: strict-origin-when-cross-origin或更严格策略 | 不设Referrer-Policy,URL中的敏感参数泄露给第三方 | 信息泄露 |
| V3.4.6 | 每个响应用CSP frame-ancestors 'self'(或指定白名单)。不依赖已过时的X-Frame-Options | 不限制页面嵌套;仅用X-Frame-Options | 点击劫持 |
| V3.4.7 | CSP头配置report-uri或report-to指令收集违规报告 | CSP违规无处上报,无法发现策略问题 | 安全盲区 |
| V3.4.8 | HTML响应加Cross-Origin-Opener-Policy: same-origin | 不设COOP,跨窗口可通过window.opener访问 | 标签页劫持、帧计数 |
V3.5 浏览器源分离
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.5.1 | 敏感操作加CSRF Token,或使用自定义请求头(如X-Requested-With)校验来源 | 敏感POST接口不做来源校验 | CSRF |
| V3.5.2 | 若依赖CORS预检防护:确保敏感接口强制触发预检(如Content-Type: application/json + 校验Origin头) | 敏感接口接受text/plain等简单请求Content-Type | CSRF绕过预检 |
| V3.5.3 | 敏感操作使用POST/PUT/PATCH/DELETE。校验Sec-Fetch-*头 | 敏感操作用GET(如GET /api/delete?id=1) | CSRF、缓存泄露 |
| V3.5.4 | 不同应用部署在不同域名/主机名 | 多个应用共享同一域名,Cookie互相可见 | 跨应用攻击 |
| V3.5.5 | postMessage接收端校验event.origin白名单 + 验证消息格式 | 不校验origin,信任所有postMessage消息 | 跨域消息伪造 |
| V3.5.6 | 全面禁用JSONP,改用CORS方案 | 任何端点启用JSONP回调 | XSSI |
| V3.5.7 | 需授权数据通过JSON API返回(Content-Type: application/json) | 把敏感数据放在JS文件中(var data = {...}) | XSSI |
| V3.5.8 | 认证资源设Cross-Origin-Resource-Policy: same-origin;校验Sec-Fetch-*头 | 认证图片/脚本可被任意跨域页面嵌入加载 | 跨域资源盗用 |
V3.6 外部资源完整性
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.6.1 | CDN资源加SRI校验:<script integrity="sha384-..." crossorigin="anonymous">,且资源必须带版本号 | 引用CDN脚本不加integrity属性;引用CDN上的最新版(无锁版本) | CDN投毒、供应链攻击 |
V3.7 其他浏览器安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V3.7.1 | 仅使用现代受支持的前端技术 | 使用Flash、ActiveX、Silverlight、Java Applet、NACL | 过时技术漏洞 |
| V3.7.2 | 跳转外部域名用白名单控制,仅允许跳转到预定义的可信域 | redirect_url参数可跳转到任意外部域名 | 开放重定向 |
| V3.7.3 | 跳转到外部URL时显示提示页,让用户确认或取消 | 静默跳转到非本站域名 | 钓鱼 |
| V3.7.4 | 将顶级域名提交到HSTS Preload List(hstspreload.org) | 仅依赖Strict-Transport-Security响应头 | 首次访问HTTPS降级 |
| V3.7.5 | 检测浏览器安全特性支持情况,不支持时警告或阻止 | 对老旧浏览器不做任何安全功能检查 | 降级攻击 |
V4 API 和 Web 服务
V4.1 通用 Web 服务安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V4.1.1 | 每个HTTP响应设正确的Content-Type+charset=utf-8 | 不设Content-Type;JSON响应返回text/html | MIME混淆XSS |
| V4.1.2 | 仅浏览器页面端点做HTTP→HTTPS自动重定向;API/内部端点不做透明重定向 | 所有端点无差别HTTP→HTTPS自动跳转,掩盖了明文传输问题 | 敏感数据明文泄露 |
| V4.1.3 | 代理头(X-Forwarded-For、X-Real-IP、X-User-ID)从可信中间层设置,不允许终端用户覆盖 | 应用直接信任客户端传来的X-Forwarded-For头 | IP伪造、身份伪造 |
| V4.1.4 | 仅允许应用显式支持的HTTP方法,其余返回405 Method Not Allowed | 所有HTTP方法均可到达处理器(如PUT/DELETE被意外暴露) | 未授权操作 |
| V4.1.5 | 高敏感交易使用消息级数字签名(如JWS签名请求体) | 仅靠TLS传输加密保护高价值交易 | 中间人篡改 |
V4.2 HTTP 消息结构验证
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V4.2.1 | 所有组件(LB/WAF/应用)一致使用正确的HTTP版本消息边界机制。HTTP/1.x有Transfer-Encoding时忽略Content-Length | 前后端对Transfer-Encoding和Content-Length处理不一致 | HTTP请求走私 |
| V4.2.2 | 生成HTTP消息时Content-Length与实际内容长度一致 | Content-Length和实际body长度不匹配 | 请求走私 |
| V4.2.3 | HTTP/2和HTTP/3中禁止Transfer-Encoding等连接专用头 | HTTP/2消息中携带Transfer-Encoding头 | 响应拆分、头注入 |
| V4.2.4 | HTTP/2和HTTP/3请求拒绝头字段中包含\r、\n、\r\n的请求 | 不校验HTTP/2头中的换行符 | HTTP头注入 |
| V4.2.5 | 应用构建的请求URI和头做长度限制,避免生成超长Cookie/Authorization头 | 允许Cookie/URL无限增长,导致服务端永久返回413错误 | Cookie炸弹、DoS |
V4.3 GraphQL
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V4.3.1 | 实施查询深度限制 + 复杂度限制 + 查询白名单(持久化查询) | 允许无限深度嵌套查询;不做查询成本分析 | GraphQL DoS |
| V4.3.2 | 生产环境禁用GraphQL Introspection({__schema{types{name}}}) | 生产环境可查询完整Schema | 信息泄露 |
V4.4 WebSocket
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V4.4.1 | WebSocket必须使用WSS(TLS加密) | 使用ws://明文WebSocket | 中间人 |
| V4.4.2 | 握手时校验Origin头白名单 | 不验证WebSocket握手的Origin | 跨站WebSocket劫持 |
| V4.4.3 | WebSocket不能用标准会话管理时,使用专用Token,满足会话安全要求 | WebSocket通道无认证/授权机制 | 未授权访问 |
| V4.4.4 | WebSocket Token需通过已认证的HTTPS会话获取/验证 | WebSocket Token通过不安全通道传递 | Token窃取 |
V5 文件处理
V5.1 文件处理文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V5.1.1 | 文档化每个上传点的:允许文件类型、扩展名、最大大小(含解压大小)、恶意文件检测响应策略 | 无文档说明允许的文件类型和大小限制 | 规范缺失 |
V5.2 文件上传和内容
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V5.2.1 | 限制上传文件大小,确保处理不会导致OOM或DoS | 无文件大小限制 | DoS |
| V5.2.2 | 校验文件扩展名 + Magic Bytes + 内容三合一验证;图片做重写处理 | 仅靠扩展名判断文件类型 | 恶意文件上传 |
| V5.2.3 | 解压前检查压缩文件的解压后大小和文件数量上限 | 不限制解压后大小,直接解压 | Zip炸弹 |
| V5.2.4 | 实施每用户文件配额(数量+大小) | 单用户可无限上传 | 存储耗尽 |
| V5.2.5 | 拒绝压缩包中的符号链接(除非有业务需要+白名单) | 允许上传含symlink的zip包 | 任意文件读取 |
| V5.2.6 | 限制上传图片最大像素尺寸 | 允许上传超大像素图片(如100000x100000) | 像素洪水DoS |
V5.3 文件存储
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V5.3.1 | 上传文件存储路径不在Web可执行目录中,或通过Web服务器配置禁止执行 | 上传的.php/.jsp文件放在webroot下可直接访问执行 | WebShell |
| V5.3.2 | 文件路径使用内部生成的随机名,不使用用户提交的文件名。必须使用用户名时做严格校验 | open("/uploads/" + userFilename)不做过滤 | 路径遍历、LFI/RFI、SSRF |
| V5.3.3 | 解压时忽略文件中的路径信息(如../../) | 直接按zip内路径解压文件 | Zip Slip |
V5.4 文件下载
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V5.4.1 | 忽略用户提交的文件名,在Content-Disposition头中使用服务端生成的安全文件名 | Content-Disposition: attachment; filename="{userInput}" | 头注入 |
| V5.4.2 | 文件名按RFC 6266编码,对特殊字符做转义 | 文件名含未编码的换行符、引号等 | 响应头注入 |
| V5.4.3 | 来自不可信源的文件经杀毒扫描后才提供下载 | 直接转发未扫描的外部文件 | 恶意软件分发 |
V6 认证
V6.1 认证文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 | |
| V6.1.1 | 文档化防暴力破解策略(速率限制/锁定阈值/解锁方式),明确不能导致恶意锁定 | 无防暴力破解方案文档 | 撞库、暴破 | |
| V6.1.2 | 维护上下文禁用词表(公司名、产品名、项目名等),禁止用于密码 | 不维护业务相关词汇的密码黑名单 | 弱密码 | |
| V6.1.3 | 多种认证路径全部文档化,安全控制和强度在所有路径一致执行 | 有些认证入口没记录,安全强度不一致 | 绕过强认证 | |
V6.2 密码安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.2.1 | 密码最低8位,需组合大小写字符数字(建议15位以上) | 允许空密码或少于8位 | 弱密码 |
| V6.2.2 | 提供密码修改功能 | 用户无法自行改密码 | 凭证泄露无法止损 |
| V6.2.3 | 修改密码需同时验证旧密码和新密码 | 改密码不要求输入旧密码 | 会话劫持后改密码 |
| V6.2.4 | 注册/改密码时比对至少Top 3000常用密码黑名单 | 不检查常见密码 | 弱密码 |
| V6.2.5 | 允许任意字符组合的密码,不做字符类型限制 | 强制要求"大写+小写+数字+特殊字符"的复杂度规则 | 降低密码空间 |
| V6.2.6 | 密码输入框type="password"默认掩码,可提供"显示密码"切换 | 密码明文显示在输入框中 | 肩窥 |
| V6.2.7 | 允许粘贴密码,允许浏览器密码管理器和第三方密码管理器 | 禁用paste事件;阻止密码管理器填充 | 阻碍用户使用强密码 |
| V6.2.8 | 密码原样验证,不做任何截断或大小写转换 | 密码只取前N位验证;统一转小写后比对 | 密码强度削弱 |
| V6.2.9 | 允许密码至少64字符长 | 限制密码最大长度为20字符或更短 | 限制密码强度 |
| V6.2.10 | 密码不设过期强制轮换;仅在发现泄露或用户主动修改时更换 | 强制每90天改密码 | 密码弱化(用户选简单密码) |
| V6.2.11 | 使用业务上下文禁用词表阻止弱密码(如公司名+123) | 不检查业务相关词汇 | 可猜测密码 |
| V6.2.12 | 注册/改密码时比对已泄露密码库(如HaveIBeenPwned API) | 不检查密码是否在已知泄露库中 | 撞库 |
V6.3 通用认证安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.3.1 | 按文档实施防暴力破解控制(渐进延迟/账户锁定/CAPTCHA) | 登录接口无频率限制 | 撞库、暴力破解 |
| V6.3.2 | 删除或禁用默认账号(root/admin/sa/test) | 默认账号保留在生产系统中 | 默认凭证利用 |
| V6.3.3 | 使用MFA或多种单因素组合。L3要求至少一个因素为抗钓鱼的硬件认证(FIDO2密钥) | 仅用户名+密码单因素认证 | 凭证窃取 |
| V6.3.4 | 所有认证路径均有文档,安全控制一致执行,无隐藏入口 | 存在未记录的认证旁路/测试入口 | 认证绕过 |
| V6.3.5 | 可疑认证(异地/异常设备/多次失败后成功)通知用户 | 异常登录不告警 | 账号被盗不知 |
| V6.3.6 | 不用邮件作为认证因素(邮件不安全) | 邮件链接作为MFA因素 | 邮件劫持 |
| V6.3.7 | 认证信息变更(密码重置/邮箱修改)后通知用户 | 密码被改/邮箱被换时无通知 | 静默接管账号 |
| V6.3.8 | 认证失败时返回统一的通用错误信息和一致的响应时间 | "用户名不存在"和"密码错误"返回不同消息/响应码/耗时 | 用户名枚举 |
V6.4 认证因素生命周期和恢复
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.4.1 | 系统生成初始密码用CSPRNG,遵循密码策略,短时间或首次使用后过期 | 初始密码为固定值(如abc123);初始密码永不过期 | 默认凭证 |
| V6.4.2 | 不使用密码提示和"安全问题" | "你妈妈的姓?""你的宠物名?" | 社工猜测 |
| V6.4.3 | 忘记密码流程不绕过已启用的MFA | 密码重置链接可跳过MFA直接登录 | MFA绕过 |
| V6.4.4 | MFA设备丢失时,恢复流程身份验证强度等同于初次注册 | MFA丢失后仅靠邮件即可恢复 | MFA旁路 |
| V6.4.5 | 认证凭证到期前提前通知 + 自动提醒 | 证书/密钥过期无人知晓,系统突然中断 | 服务中断 |
| V6.4.6 | 管理员可发起密码重置,但不能查看/设置用户的新密码 | 管理员可直接给用户设密码(管理员就知道密码了) | 内部人员威胁 |
V6.5 通用 MFA 要求
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.5.1 | OTP/查找密钥/带外验证码一次性使用后立即失效 | OTP可重复使用 | OTP重放 |
| V6.5.2 | 低熵查找密钥(<112位)存储时用密码哈希+32位盐;高熵的可用标准哈希 | 查找密钥明文存储 | 密钥泄露 |
| V6.5.3 | OTP种子/查找密钥用CSPRNG生成 | 使用Math.random()或时间戳生成OTP种子 | 可预测OTP |
| V6.5.4 | 查找密钥和带外验证码至少20位熵(≥4位随机字母数字或≥6位数字) | 4位纯数字短信验证码(仅13位熵) | 暴力破解验证码 |
| V6.5.5 | 带外验证码最长10分钟过期;TOTP最长30秒有效期 | 验证码永不过期或有效期过长 | 验证码窃取利用 |
| V6.5.6 | 所有认证因素(含物理设备)支持即时撤销 | 丢失的硬件密钥无法在系统中禁用 | 被盗设备利用 |
| V6.5.7 | 生物识别仅作辅助因素,必须配合"你有的"或"你知道的" | 仅指纹/面部就能登录 | 生物特征无法更换 |
| V6.5.8 | TOTP时间源用服务端可信NTP,不用客户端时间 | 用客户端时钟验证TOTP | 时钟篡改绕过 |
V6.6 带外认证机制
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.6.1 | 电话/短信OTP仅在号码已验证+提供更强替代+告知风险时才提供。L3禁用短信/电话OTP | 仅提供短信验证码作为唯一MFA选项 | SIM Swap |
| V6.6.2 | 带外验证码绑定原始认证请求,不能跨请求使用 | 验证码不绑定会话,任何人拿到码都能用 | 验证码劫持 |
| V6.6.3 | 带外验证码加速率限制,建议≥64位熵 | 短信验证码无输入次数限制 | 验证码暴破 |
| V6.6.4 | 推送通知MFA加速率限制 + 数字匹配 | 允许无限发送推送通知 | 推送轰炸(MFA Fatigue) |
V6.7 加密认证机制
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.7.1 | 认证证书防篡改存储(权限最小化/完整性校验) | 证书文件权限777/可被任何进程修改 | 证书篡改 |
| V6.7.2 | 认证挑战nonce≥64位,统计唯一或设备生命周期内唯一 | nonce可预测或长度不足 | 重放攻击 |
V6.8 身份提供者认证
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V6.8.1 | 多IdP时用IdP ID + 用户ID组合唯一标识用户 | 不同IdP的同名用户映射为同一账户 | 身份冒充 |
| V6.8.2 | 始终验证认证断言(JWT/SAML)的数字签名,拒绝无签名或签名无效的 | 不验证JWT签名;接受alg: none | 身份伪造 |
| V6.8.3 | SAML断言在有效期内仅处理一次 | 同一SAML断言可重复使用 | 重放攻击 |
| V6.8.4 | 验证IdP返回的认证强度信息(OIDC的acr/amr/auth_time)。无此信息时假定最低强度 | 不检查IdP实际使用的认证方式 | 降级认证 |
V7 会话管理
V7.1 会话管理文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V7.1.1 | 文档化会话不活动超时和绝对超时,含偏离NIST的理由 | 无会话超时策略文档 | 规范缺失 |
| V7.1.2 | 文档化每账户允许的最大并发会话数和达到上限时的行为 | 不限制并发会话,无处理策略 | 会话滥用 |
| V7.1.3 | SSO等联合身份系统的会话协调策略全部文档化 | SSO退出后子系统会话仍然有效,且无文档说明 | 联合会话不一致 |
V7.2 基本会话管理安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V7.2.1 | 会话Token验证在后端可信层执行 | 在前端JS验证会话有效性 | 会话伪造 |
| V7.2.2 | 使用动态生成的Token(自包含JWT或引用Token) | 使用固定API Key/静态密钥作为会话标识 | 会话劫持 |
| V7.2.3 | 引用Token用CSPRNG生成,≥128位熵 | Token可预测(时间戳/自增ID/弱随机数) | 会话劫持 |
| V7.2.4 | 用户登录(含重新认证)时生成新Token,销毁旧Token | 登录前后使用同一个Token | 会话固定 |
V7.3 会话超时
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V7.3.1 | 设置不活动超时,超时后强制重新认证 | 会话永不因不活动过期 | 无人值守终端利用 |
| V7.3.2 | 设置绝对最大生命周期,到期后强制重新认证 | 会话无绝对过期时间,只要活跃就永不过期 | 长期会话劫持 |
V7.4 会话终止
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V7.4.1 | 登出/过期时服务端立即使会话无效。JWT用吊销列表/签名轮换 | 前端清Cookie但后端Token仍有效 | 登出后仍可用 |
| V7.4.2 | 账户禁用/删除时终止所有活跃会话 | 员工离职后其会话仍然有效 | 离职员工访问 |
| V7.4.3 | 改密码/更新MFA后,提供终止其他所有会话的选项 | 改密码后旧会话继续有效 | 被盗会话持续使用 |
| V7.4.4 | 所有需认证的页面提供明显的登出入口 | 找不到登出按钮 | 会话暴露 |
| V7.4.5 | 管理员可强制终止任一用户/所有用户的会话 | 管理员无法踢掉被盗账号的活跃会话 | 应急响应缺失 |
V7.5 防御会话滥用
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V7.5.1 | 修改敏感属性(邮箱/手机/MFA配置)前要求完全重新认证 | 已登录用户直接改邮箱不需要再次输入密码/MFA | 会话劫持升级 |
| V7.5.2 | 用户可查看所有活跃会话并逐个终止(需再次认证确认) | 用户无法看到或管理自己的活跃会话 | 被盗会话不知 |
| V7.5.3 | 高敏感操作(大额转账等)要求二次认证/验证 | 高敏感操作与普通操作认证要求相同 | 会话劫持后高价值操作 |
V7.6 联合重新认证
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V7.6.1 | RP和IdP会话按文档协调,达到IdP最大时间时触发重新认证 | RP会话比IdP会话长很多,IdP退出后RP仍有效 | 会话不同步 |
| V7.6.2 | 会话创建需要用户明确操作/同意 | 后台静默创建会话(无用户交互) | 会话劫持 |
V8 授权
V8.1 授权文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V8.1.1 | 文档化功能级别和数据级别的访问控制规则 | 授权规则无文档,全靠代码自描述 | 授权遗漏 |
| V8.1.2 | 文档化字段级别的读写权限控制(含状态依赖规则) | 不区分字段级权限,要么全给要么全不给 | 数据过度暴露 |
| V8.1.3 | 文档化环境/上下文属性(时间/位置/IP/设备)在安全决策中的使用 | 不考虑上下文信息做授权决策 | 无上下文防护 |
| V8.1.4 | 文档化环境因素的评估阈值和响应动作(允许/挑战/拒绝/升级认证) | 仅有简单角色判断,无上下文感知 | 粗粒度授权 |
V8.2 通用授权设计
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V8.2.1 | 功能级授权:每个操作检查当前用户是否有显式权限 | 仅靠隐藏URL/按钮做权限控制 | 越权访问功能 |
| V8.2.2 | 数据级授权:访问每条数据前检查当前用户对该特定资源的权限 | GET /api/orders/123不校验123是否属于当前用户 | IDOR/BOLA |
| V8.2.3 | 字段级授权:控制用户对特定字段的读/写权限 | API返回所有字段(含管理员字段)给普通用户 | BOPLA |
| V8.2.4 | 实施自适应安全控制(基于时间/位置/IP/设备),在会话开始和进行中持续评估 | 仅登录时做一次环境检查,之后不再验证 | 会话劫持后无检测 |
V8.3 操作级别授权
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V8.3.1 | 授权在后端可信层执行 | 仅前端JS隐藏按钮/菜单作权限控制 | 前端绕过 |
| V8.3.2 | 权限变更立即生效。JWT等自包含Token需配合变更告警+回滚机制 | 改了权限但Token未过期前仍有旧权限 | 权限延迟生效被利用 |
| V8.3.3 | 权限决策基于发起用户的权限,不用中介服务的权限 | 微服务A用自己的服务账号权限替代用户权限调用微服务B | 权限升级 |
V8.4 其他授权考量
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V8.4.1 | 多租户应用实施租户隔离,操作不能影响无权限的租户 | 租户A可通过改ID访问租户B的数据 | 跨租户攻击 |
| V8.4.2 | 管理接口实施多层安全(身份验证+设备安全+上下文风险),不仅靠网络位置 | 管理后台仅靠内网IP白名单保护 | 管理接口突破 |
V9 自包含令牌 (Self-contained Token)
V9.1 令牌来源和完整性
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V9.1.1 | 始终验证Token的数字签名/MAC后才使用内容 | 不验签直接base64解码JWT payload使用 | Token伪造 |
| V9.1.2 | 签名算法用白名单限定。禁止none算法 | 接受JWT的alg: none;允许HS256和RS256混用 | 算法混淆攻击 |
| V9.1.3 | 验证密钥仅来自预配置的可信源。JWT的jku/x5u/jwk头对照白名单验证 | 直接使用JWT头中指向攻击者服务器的jkuURL获取公钥 | 密钥注入 |
V9.2 令牌内容
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V9.2.1 | 严格校验Token时间窗口(JWT的nbf和exp) | 不验证Token过期时间 | 过期Token利用 |
| V9.2.2 | 区分Token类型:Access Token只用于授权,ID Token只用于身份证明 | Access Token和ID Token混用 | Token误用 |
| V9.2.3 | 验证Token的aud受众匹配当前服务的标识 | 不校验aud,任何服务的Token都接受 | Token跨服务盗用 |
| V9.2.4 | 同一密钥签发多个受众的Token时,必须包含唯一受众限制 | 同一密钥签发的Token可在任何服务使用 | Token受众混淆 |
V10 OAuth 和 OIDC
V10.1 通用 OAuth/OIDC 安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.1.1 | Token仅发给需要的组件。BFF模式下Access/Refresh Token只留后端 | Access Token暴露在浏览器JS中 | Token窃取 |
| V10.1.2 | 客户端仅接受自己发起的授权流程返回的值。PKCE code_verifier/state/nonce绑定当前会话 | 不用PKCE和state;不绑定会话 | 授权码注入、CSRF |
V10.2 OAuth 客户端
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.2.1 | 授权码流程使用PKCE或验证state参数防CSRF | 不使用PKCE,不校验state | CSRF触发Token请求 |
| V10.2.2 | 多授权服务器场景验证iss参数防混淆攻击 | 不验证Token/响应来自哪个授权服务器 | 授权服务器混淆 |
| V10.2.3 | 仅请求必要的scope(最小权限) | 请求所有可用scope | 过度授权 |
V10.3 OAuth 资源服务器
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.3.1 | 验证Access Token的aud受众匹配本服务 | 不检查aud,接受发给其他服务的Token | Token滥用 |
| V10.3.2 | 基于Token中的sub/scope/authorization_details做授权决策 | 不检查Token内的权限声明 | 越权访问 |
| V10.3.3 | 用iss + sub组合唯一标识用户(防止跨IdP重分配) | 仅用sub标识用户 | 身份冒充 |
| V10.3.4 | 需要特定认证强度时,验证Token的acr/amr/auth_time满足要求 | 不检查Token中的认证方式信息 | 降级认证 |
| V10.3.5 | 使用发送方绑定Token(mTLS或DPoP)防Token盗用 | 使用Bearer Token不做发送方绑定 | Token窃取重放 |
V10.4 OAuth 授权服务器
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.4.1 | redirect_uri用精确字符串匹配白名单校验 | 正则匹配或域名模糊匹配redirect_uri | 开放重定向→Token窃取 |
| V10.4.2 | 授权码一次性使用,二次使用时撤销已发的所有Token | 授权码可多次换Token | 授权码重放 |
| V10.4.3 | 授权码短期有效(L1/L2≤10分钟,L3≤1分钟) | 授权码有效期过长 | 授权码窃取利用窗口 |
| V10.4.4 | 仅允许客户端需要的授权类型。禁用Implicit和Password授权 | 允许response_type=token(隐式流程) | Token泄露(URL fragment) |
| V10.4.5 | 公共客户端的Refresh Token用DPoP/mTLS绑定发送方,或使用Token轮换(用后即废+检测重用) | 公共客户端的Refresh Token不做发送方绑定也不轮换 | Refresh Token窃取 |
| V10.4.6 | 授权码流程强制PKCE:要求code_challenge,拒绝plain方法,验证code_verifier | 不要求PKCE;接受code_challenge_method=plain | 授权码拦截 |
| V10.4.7 | 动态客户端注册须验证元数据+用户同意+风险提示 | 不验证动态注册的客户端信息 | 恶意客户端注册 |
| V10.4.8 | Refresh Token设绝对过期时间(即使使用滑动过期也需设上限) | Refresh Token永不过期 | 长期Token泄露 |
| V10.4.9 | 用户可通过管理界面撤销Refresh Token和引用Access Token | 用户无法撤销已授权的Token | 被盗Token无法止损 |
| V10.4.10 | 机密客户端向授权服务器的后端请求(Token/PAR/撤销)必须认证客户端身份 | 后端Token请求不验证客户端身份 | 客户端冒充 |
| V10.4.11 | 仅分配客户端需要的scope | 给客户端分配超出需要的scope | 过度授权 |
| V10.4.12 | 仅允许客户端需要的response_mode | 允许客户端使用任意response_mode | 意外的Token暴露方式 |
| V10.4.13 | 授权码流程必须配合PAR(推送授权请求) | 不使用PAR,授权参数在URL中可被篡改 | 请求篡改 |
| V10.4.14 | 仅发行发送方绑定的Access Token(mTLS或DPoP) | 发行无绑定的Bearer Token | Token窃取重放 |
| V10.4.15 | 服务端客户端的authorization_details须来自客户端后端(通过PAR/JAR)确保用户未篡改 | 授权详情从前端传入不做来源验证 | 授权详情篡改 |
| V10.4.16 | 机密客户端使用基于公钥的强认证(mTLS/private_key_jwt),抗重放 | 使用client_secret_post等弱认证方式 | 客户端凭证泄露 |
V10.5 OIDC 客户端
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.5.1 | 验证ID Token的nonce与请求中发送的nonce匹配 | 不验证nonce | ID Token重放 |
| V10.5.2 | 用sub声明唯一标识用户(不可被重分配) | 用email等可变字段标识用户 | 身份混淆 |
| V10.5.3 | 验证授权服务器元数据的issuer与预配置的完全匹配,不匹配则拒绝 | 不验证issuer来源 | 恶意IdP冒充 |
| V10.5.4 | 验证ID Token的aud等于本客户端的client_id | 不验证aud | 跨客户端Token盗用 |
| V10.5.5 | OIDC后端通道登出:验证logout Token类型为logout+jwt,含event声明,不含nonce,设短过期时间 | 不验证logout Token类型和内容 | 强制登出DoS |
V10.6 OpenID 提供者
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.6.1 | 仅允许code/ciba/id_token/id_token code响应模式。禁止token(隐式流程) | 允许response_type=token | Token泄露 |
| V10.6.2 | 强制登出需用户明确确认或验证id_token_hint等参数 | 无需确认即可触发任意用户登出 | 强制登出DoS |
V10.7 同意管理
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V10.7.1 | 每次授权征得用户同意。客户端身份不可确认时必须显式提示 | 静默自动授权不提示用户 | 未授权的授权 |
| V10.7.2 | 同意界面清晰展示请求的权限范围、客户端身份、授权有效期 | 同意页面仅显示"是否允许"不说明具体权限 | 用户不知情授权 |
| V10.7.3 | 用户可查看、修改、撤销已授予的授权 | 授权一旦给出无法撤回 | 过度授权持续 |
V11 密码学
V11.1 密码学清单和文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.1.1 | 文档化密钥管理策略(遵循NIST SP 800-57),密钥不过度共享 | 密钥管理无文档;一个密钥到处用 | 密钥泄露扩散 |
| V11.1.2 | 维护密码学资产清单(所有密钥/算法/证书),含使用位置和保护的数据类型 | 不知道系统用了哪些密钥和算法 | 密码学盲区 |
| V11.1.3 | 使用密码学发现工具识别系统中所有加密/哈希/签名实例 | 仅人工审计密码学使用 | 遗漏弱算法 |
| V11.1.4 | 维护密码学清单,包含后量子密码学迁移计划 | 不考虑量子计算威胁 | 未来密码学突破 |
V11.2 安全密码学实现
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.2.1 | 使用业界验证的密码学库(如OpenSSL/libsodium/Bouncy Castle) | 自己实现加密算法 | 实现缺陷 |
| V11.2.2 | 设计密码学敏捷架构:算法/密钥/模式可配置化替换,支持PQC升级 | 算法硬编码,更换需要大规模改代码 | 无法应对算法突破 |
| V11.2.3 | 所有加密原语≥128位安全强度(如AES-256、ECC-256、RSA-3072) | 使用DES、3DES、RSA-1024 | 暴力破解 |
| V11.2.4 | 密码学操作实现为常量时间,无短路比较 | if (hmac[0] != expected[0]) return false 逐字节比较 | 计时侧信道 |
| V11.2.5 | 密码学模块安全失败,错误信息不泄露内部状态 | 返回"padding incorrect"等详细密码学错误信息 | Padding Oracle |
V11.3 加密算法
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.3.1 | 使用安全块模式(GCM/CTR/CBC+HMAC)和安全填充(OAEP) | 使用ECB模式;使用PKCS#1 v1.5填充 | 模式攻击 |
| V11.3.2 | 仅用经批准的密码和模式(如AES-GCM) | 使用RC4、Blowfish等过时算法 | 密码学弱点 |
| V11.3.3 | 加密数据需认证加密(AEAD如AES-GCM)或加密+MAC | 仅加密不做完整性校验 | 密文篡改 |
| V11.3.4 | Nonce/IV不重复使用于同一密钥+数据对,生成方式适合所用算法 | AES-GCM使用相同Key+Nonce加密不同数据 | Nonce重用攻击 |
| V11.3.5 | 加密+MAC组合使用Encrypt-then-MAC模式 | MAC-then-Encrypt;Encrypt-and-MAC | MAC验证时序攻击 |
V11.4 哈希和基于哈希的函数
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.4.1 | 使用SHA-256/SHA-3/BLAKE2等经批准的哈希函数 | 使用MD5/SHA-1做任何密码学用途 | 碰撞攻击 |
| V11.4.2 | 密码存储用bcrypt/scrypt/Argon2id,参数调到当前硬件的合理耗时(≥100ms) | 用SHA-256/MD5直接哈希密码;bcrypt cost factor过低 | 密码暴破 |
| V11.4.3 | 数字签名哈希需抗碰撞≥256位输出;仅抗第二原像可用≥128位 | 数字签名使用SHA-1 | 签名伪造 |
| V11.4.4 | 从密码派生密钥用PBKDF2/scrypt/Argon2(含密钥拉伸) | 直接用密码做AES密钥 | 密码暴破 |
V11.5 随机值
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.5.1 | 安全随机数用CSPRNG(/dev/urandom、SecureRandom、crypto.getRandomValues),≥128位熵 | Math.random()、rand()、UUID作为安全令牌 | 可预测随机数 |
| V11.5.2 | 随机数生成器高并发下仍安全工作 | 高负载时退化为弱随机源 | 降级攻击 |
V11.6 公钥密码学
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.6.1 | 密钥生成/签名使用经批准的算法和安全参数 | 生成易受费马因式分解攻击的RSA密钥 | 弱密钥 |
| V11.6.2 | 密钥交换用安全参数的DH/ECDH | 使用弱DH参数(如512位) | 密钥协商攻击 |
V11.7 使用中数据密码学
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V11.7.1 | 启用全内存加密保护处理中的敏感数据 | 敏感数据在内存中明文存放 | 内存转储泄露 |
| V11.7.2 | 数据最小化:处理时仅暴露最少数据,用完立即加密/清零 | 敏感数据解密后长期驻留内存 | 内存泄露窗口 |
V12 安全通信
V12.1 通用 TLS 安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V12.1.1 | 仅启用TLS 1.2和TLS 1.3,首选TLS 1.3 | 支持TLS 1.0/1.1/SSLv3 | 协议降级 |
| V12.1.2 | 仅启用推荐密码套件,最强优先。L3仅允许支持前向保密的套件 | 允许NULL/RC4/DES等弱密码套件 | 加密突破 |
| V12.1.3 | mTLS客户端证书使用前验证可信 | 不验证客户端证书链 | 客户端伪造 |
| V12.1.4 | 启用OCSP Stapling证书吊销检查 | 不做证书吊销检查 | 使用已吊销证书 |
| V12.1.5 | 启用ECH(Encrypted Client Hello)保护SNI元数据 | TLS握手明文暴露访问的域名 | SNI泄露 |
V12.2 面向外部的 HTTPS
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V12.2.1 | 对外通信全部TLS加密,不回退明文 | 允许HTTP回退 | 中间人 |
| V12.2.2 | 对外服务使用公开受信任的CA证书 | 使用自签名证书面向公网用户 | 证书不可信 |
V12.3 服务间通信安全
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V12.3.1 | 所有内/外部连接(含SSH/数据库/监控)全部加密 | 内网服务间明文通信("内网安全") | 内网横向移动 |
| V12.3.2 | TLS客户端验证服务端证书 | 客户端跳过证书验证(verify=False) | 中间人 |
| V12.3.3 | 内部HTTP服务间通信全部TLS | 内部微服务间HTTP明文通信 | 内网嗅探 |
| V12.3.4 | 内部TLS使用受信任证书。自签名证书须在消费端配置信任特定CA/证书 | 内部服务配置为信任所有证书 | 证书伪造 |
| V12.3.5 | 内部服务间使用mTLS双向认证。微服务考虑用Service Mesh | 内部服务间不做身份认证 | 服务冒充 |
V13 配置
V13.1 配置文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V13.1.1 | 文档化所有外部通信需求(外部依赖+用户可指定的外部连接) | 不记录应用对外连接情况 | 未知外部依赖 |
| V13.1.2 | 文档化每个服务的最大并发连接数+达到上限时的行为+恢复策略 | 无连接池配置文档 | 连接池耗尽DoS |
| V13.1.3 | 文档化每个外部依赖的资源管理策略(超时/重试限制/退避算法)。同步HTTP操作用短超时+禁止或严格限制重试 | 无超时配置,重试无限制 | 级联延迟、资源耗尽 |
| V13.1.4 | 文档化安全关键密钥及其轮换计划 | 密钥无轮换计划 | 密钥泄露后持续可用 |
V13.2 后端通信配置
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V13.2.1 | 后端组件间认证用独立服务账号/短期Token/证书,不用长期固定凭证 | 所有后端服务共享一个永不过期的API Key | 凭证泄露→全线沦陷 |
| V13.2.2 | 后端通信账号遵循最小权限 | 服务用root/admin账号连数据库 | 权限过大 |
| V13.2.3 | 服务认证凭证不用默认值(root/root、admin/admin) | 生产环境使用默认密码 | 默认凭证 |
| V13.2.4 | 外发请求目标用白名单限制(应用层/Web服务器/防火墙) | 服务端可请求任意外部地址 | SSRF |
| V13.2.5 | Web/应用服务器配置出站白名单 | 服务器无出站限制 | SSRF |
| V13.2.6 | 每个外部连接按文档配置最大连接数/超时/重试策略 | 连接配置无规范,使用库默认值 | 资源耗尽 |
V13.3 密钥管理
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V13.3.1 | 使用密钥管理工具(Vault/KMS/HSM)管理所有密钥。L3须用HSM | 密钥写在代码/配置文件/环境变量中 | 密钥泄露 |
| V13.3.2 | 密钥访问遵循最小权限 | 所有服务都能访问所有密钥 | 密钥过度暴露 |
| V13.3.3 | 密码操作在隔离安全模块(HSM/Vault)中执行,密钥不出模块 | 密钥加载到应用内存中使用 | 密钥泄露 |
| V13.3.4 | 密钥配置自动过期和轮换 | 密钥永不过期 | 长期密钥泄露 |
V13.4 意外信息泄露
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V13.4.1 | 部署时删除或不可访问.git/.svn等源码管理目录 | 生产环境可直接访问/.git/config | 源码泄露 |
| V13.4.2 | 生产环境禁用所有调试模式 | 生产开着debug=True/dev-tools | 调试信息泄露 |
| V13.4.3 | Web服务器禁用目录浏览(除非有意为之) | 访问目录返回文件列表 | 文件信息泄露 |
| V13.4.4 | 生产环境禁用HTTP TRACE方法 | TRACE方法可用 | XST(跨站追踪) |
| V13.4.5 | 内部API文档和监控端点不对外暴露 | Swagger UI / Prometheus metrics 对公网可访问 | 信息泄露 |
| V13.4.6 | 不暴露后端组件的详细版本号 | 响应头/错误页泄露Apache/2.4.51、PHP/8.1.2 | 版本指纹→精准漏洞利用 |
| V13.4.7 | Web服务器白名单限制可提供文件的扩展名 | 可下载.bak/.sql/.conf/.env等文件 | 配置/源码泄露 |
V14 数据保护
V14.1 数据保护文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V14.1.1 | 所有敏感数据已识别并分级(含Base64编码数据、JWT明文Payload等) | 不知道系统处理了哪些敏感数据 | 数据保护盲区 |
| V14.1.2 | 每个保护级别有完整的保护要求(加密/完整性/日志/保留/隐私增强) | 无按级别定义的保护措施 | 保护不足或不一致 |
V14.2 通用数据保护
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V14.2.1 | 敏感数据仅放HTTP Body或Header中传输 | URL/查询字符串中包含API Key/Session Token | 日志/Referer泄露 |
| V14.2.2 | 防止敏感数据被中间层缓存(LB/CDN/代理),或用后立即清除 | 敏感API响应被CDN缓存 | 缓存泄露 |
| V14.2.3 | 敏感数据不发给第三方追踪器(GA/广告SDK等) | 用户PII发送到第三方分析工具 | 数据泄露 |
| V14.2.4 | 按照各级别文档化要求实施加密/日志/访问控制等保护措施 | 文档定义了保护要求但代码未实现 | 保护缺失 |
| V14.2.5 | 缓存机制仅缓存匹配预期Content-Type的静态响应。不存在的资源返回404/302不返回其他有效文件 | 动态敏感响应被缓存;不存在的路径返回其他文件 | Web缓存欺骗 |
| V14.2.6 | API仅返回最少必要数据(信用卡仅末4位,手机号中间脱敏) | API默认返回完整敏感数据 | 数据过度暴露 |
| V14.2.7 | 敏感数据设自动过期/定期清理策略 | 敏感数据永久保留不清理 | 历史数据泄露 |
| V14.2.8 | 用户上传文件自动清除EXIF等元数据(除非用户同意保留) | 上传的照片保留GPS坐标等元数据 | 隐私泄露 |
V14.3 客户端数据保护
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V14.3.1 | 登出/会话结束时清除客户端存储的认证数据(配合Clear-Site-Data头) | 登出后DOM/Storage中仍残留Token | 会话残留 |
| V14.3.2 | 敏感响应设Cache-Control: no-store | 含敏感数据的页面可被浏览器缓存 | 浏览器缓存泄露 |
| V14.3.3 | localStorage/sessionStorage/IndexedDB/Cookie中不存敏感数据(会话Token除外) | 把密码/个人信息存在localStorage中 | XSS窃取存储数据 |
V15 安全编码和架构
V15.1 安全编码和架构文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V15.1.1 | 文档化第三方组件漏洞修复SLA和库更新策略 | 依赖库有CVE无人管、无修复时间表 | 已知漏洞利用 |
| V15.1.2 | 维护SBOM(软件物料清单),组件来自可信仓库 | 不清楚用了哪些第三方库 | 供应链攻击 |
| V15.1.3 | 文档化耗时/资源密集功能,定义防DoS策略(异步/队列/限流) | 资源密集接口不做限制 | DoS |
| V15.1.4 | 文档标记被认为是"高风险"的第三方库 | 不评估第三方库风险 | 高风险依赖 |
| V15.1.5 | 文档标记使用"危险功能"的代码模块 | 不知道哪些代码使用了危险功能 | 攻击面不明 |
V15.2 安全架构和依赖
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V15.2.1 | 所有组件在SLA内更新 | 使用已知漏洞版本超出修复时限 | 已知CVE利用 |
| V15.2.2 | 资源密集功能实施防DoS措施(异步处理/队列/并发限制) | 耗资源接口无保护 | DoS |
| V15.2.3 | 生产环境仅含必要功能,移除测试代码/示例/开发功能 | 生产环境保留phpinfo()/test路由/debug端点 | 信息泄露、额外攻击面 |
| V15.2.4 | 第三方依赖(含传递依赖)来自预期仓库,防止依赖混淆 | 不验证包来源;内部包名与公共仓库冲突 | 依赖混淆攻击 |
| V15.2.5 | 高风险模块实施沙箱/容器化/网络隔离 | 高风险模块与核心系统同进程无隔离 | 攻陷后横向扩展 |
V15.3 防御性编码
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V15.3.1 | API仅返回必要字段子集(DTO/序列化白名单) | SELECT * FROM users后直接返回整个对象给前端 | 数据过度暴露 |
| V15.3.2 | 后端HTTP客户端禁止自动跟随重定向(除非是预期行为) | requests.get(url, allow_redirects=True)访问用户提供的URL | SSRF通过重定向绕过 |
| V15.3.3 | 每个接口白名单允许绑定的字段,防止批量赋值 | User.update(request.body)自动绑定所有提交字段(含isAdmin) | 批量赋值(Mass Assignment) |
| V15.3.4 | IP传递用可信的代理头(应用层从配置的可信代理获取真实IP) | 直接用客户端传来的X-Forwarded-For做安全决策 | IP伪造 |
| V15.3.5 | 显式声明变量类型 + 严格比较(===而非==) | PHP/JS中0 == "0" == false导致逻辑错误 | 类型混淆/类型杂耍 |
| V15.3.6 | JS中用Map()/Set()/Object.create(null)代替对象字面量存储用户数据 | userObj[userInput] = value直接操作对象属性 | 原型污染 |
| V15.3.7 | 实施HTTP参数污染防御,明确参数来源优先级 | 框架不区分query/body/cookie同名参数,攻击者利用差异绕过 | HPP |
V15.4 安全并发
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V15.4.1 | 共享对象用线程安全类型 + 锁/信号量保护 | 多线程直接读写共享变量不加锁 | 竞态条件 |
| V15.4.2 | 资源状态检查和操作作为原子操作执行 | 先if (file.exists())再file.open(),中间可被竞争 | TOCTOU |
| V15.4.3 | 一致使用锁,锁逻辑封装在资源管理代码内部 | 锁可被外部代码绕过或修改;存在死锁路径 | 死锁/锁绕过 |
| V15.4.4 | 使用线程池 + 公平调度防止线程饥饿 | 高优先级线程独占资源,低优先级永远得不到执行 | 线程饥饿DoS |
V16 安全日志和错误处理
V16.1 安全日志文档
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V16.1.1 | 文档化日志清单:每层记什么事件、什么格式、存哪里、保留多久、谁有权访问 | 不清楚系统记了什么日志 | 安全审计盲区 |
V16.2 通用日志
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V16.2.1 | 每条日志含时间(when)/位置(where)/主体(who)/事件(what)元数据 | 日志缺少关键字段,无法做事件关联分析 | 取证困难 |
| V16.2.2 | 所有日志组件时间同步,时间戳用UTC或明确时区偏移 | 不同服务器时间不同步;混用本地时区 | 时间线分析困难 |
| V16.2.3 | 日志仅输出到文档中登记的目标(文件/服务) | 日志输出到未记录的第三方服务 | 数据泄露 |
| V16.2.4 | 使用统一日志格式(如JSON结构化日志),确保日志处理器可读取和关联 | 各模块日志格式不一致 | 分析困难 |
| V16.2.5 | 敏感数据日志处理:凭证/支付信息不记录;会话Token哈希或掩码后记录 | 日志中记录明文密码/完整信用卡号 | 日志泄露敏感数据 |
V16.3 安全事件
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V16.3.1 | 记录所有认证事件(成功+失败),含认证类型/因素信息 | 只记录失败不记录成功,或完全不记录 | 无法检测异常登录 |
| V16.3.2 | 记录所有授权失败。L3需记录所有授权决策(含成功),不记录敏感数据本身 | 授权失败不记录 | 无法检测越权尝试 |
| V16.3.3 | 记录安全控制绕过尝试(输入验证失败/业务逻辑异常/反自动化触发) | 安全控制拦截后不记录 | 无法检测攻击模式 |
| V16.3.4 | 记录意外错误和安全控制失败(如TLS失败/证书错误) | 忽略/吞掉异常不记录 | 安全退化不知 |
V16.4 日志保护
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V16.4.1 | 日志内容编码处理防止注入(转义换行/特殊字符) | 用户输入直接写入日志(含\n伪造日志条目) | 日志注入/伪造 |
| V16.4.2 | 日志只读保护,防止未授权访问和篡改 | 日志文件权限777;应用可覆盖日志 | 日志篡改/销毁 |
| V16.4.3 | 日志实时传输到独立系统(SIEM/日志中心) | 日志仅存本机 | 应用被攻陷后日志被销毁 |
V16.5 错误处理
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V16.5.1 | 错误时返回通用错误消息(如"服务暂时不可用") | 返回堆栈跟踪/SQL语句/内部路径/密钥 | 信息泄露 |
| V16.5.2 | 外部依赖失败时断路器/优雅降级保证服务可用 | 数据库挂了整个应用崩溃 | 级联故障 |
| V16.5.3 | 异常时安全失败(fail-closed):验证出错→拒绝操作 | 验证异常→跳过验证继续处理(fail-open) | 异常绕过安全控制 |
| V16.5.4 | 定义全局异常捕获器,确保:①所有未处理异常被记录日志 ②异常不导致进程崩溃 | 未处理异常导致服务中断;异常信息丢失 | 服务可用性+审计缺失 |
V17 WebRTC
V17.1 TURN 服务器
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V17.1.1 | TURN服务仅允许中继到公网IP,黑名单阻止内网/环回/广播地址(IPv4+IPv6) | TURN可中继请求到127.0.0.1/10.0.0.0/169.254.169.254 | SSRF via TURN |
| V17.1.2 | TURN服务对单用户端口分配做速率限制 | 无限制,用户可开大量端口 | TURN资源耗尽 |
V17.2 媒体数据流
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V17.2.1 | DTLS证书密钥按密钥管理策略管理和保护 | DTLS密钥明文存储/不做轮换 | 密钥泄露 |
| V17.2.2 | 媒体服务器配置经批准的DTLS密码套件和DTLS-SRTP安全配置 | 使用弱密码套件 | 加密突破 |
| V17.2.3 | 媒体服务器校验SRTP认证,拒绝未认证的RTP包 | 不校验SRTP认证,允许注入RTP包 | RTP注入(DoS/媒体插入) |
| V17.2.4 | 媒体服务器容错处理畸形SRTP包,不崩溃 | 畸形SRTP包导致服务崩溃 | DoS |
| V17.2.5 | 媒体服务器抗SRTP包洪水,确保正常流量可处理 | SRTP洪水导致服务不可用 | DoS |
| V17.2.6 | 媒体服务器不受DTLS ClientHello竞态条件漏洞影响(检查已知漏洞或做测试) | 使用已知有此漏洞的版本 | DTLS竞态DoS |
| V17.2.7 | 录制机制抗SRTP洪水,不影响正常录制 | 洪水导致录制中断 | 录制DoS |
| V17.2.8 | 校验DTLS证书指纹与SDP fingerprint匹配,不匹配则终止媒体流 | 不校验DTLS证书指纹 | 中间人(媒体流劫持) |
V17.3 信令
| 编号 | ✅ 必须做 | ❌ 禁止做 | 🛡️ 防御 |
| V17.3.1 | 信令服务器实施消息级速率限制,确保洪水攻击下仍可处理合法消息 | 信令无速率限制 | 信令DoS |
| V17.3.2 | 信令服务器容错处理畸形消息(输入验证/整数溢出保护/缓冲区溢出保护) | 畸形信令消息导致服务崩溃 | 信令DoS/RCE |
附录 A:漏洞修复管理规范
A.1 漏洞等级定义
| 等级 | 定义 | 典型示例 |
| 🔴 危急(Critical) | 可直接获取系统控制权或大规模数据泄露,无需用户交互即可利用 | 未授权 RCE、SQL 注入获取全库、管理后台未授权访问、硬编码超级管理员凭证 |
| 🟠 高危(High) | 可获取敏感数据或部分系统权限,可能需要低权限账户 | 越权读取任意用户数据(IDOR)、存储型 XSS、任意文件读取、权限提升 |
| 🟡 中危(Medium) | 需要特定条件或用户交互才能利用,影响范围有限 | 反射型 XSS、CSRF 修改非关键设置、信息泄露(内部 IP/版本号/堆栈)、会话固定 |
| 🟢 低危(Low) | 安全最佳实践缺失,利用难度高或影响极小 | 缺少安全头(HSTS/CSP)、Cookie 未设 HttpOnly、目录浏览开启、详细错误页面 |
A.2 漏洞修复 SLA 时限
1. 对外服务类信息系统(面向互联网/客户的系统)
| 软件类型 | 处置方式 | 🔴 危急 + 🟠 高危 | 🟡 中危 + 🟢 低危 |
| 应用本身 / 依赖软件 / 中间件 | 临时规避 | ⏰ 48 小时内 | — (不强制临时规避) |
| 彻底整改 | ⏰ 1 个月内 | ⏰ 1 个月内 |
| 操作系统 / 数据库 / IT 基础设施 / 其它 | 临时规避 | ⏰ 15 天内 | — (不强制临时规避) |
| 彻底整改 | ⏰ 3 个月内 | 📋 择机处置 |
2. 内部信息系统(OA / 内部管理 / 办公系统)
| 软件类型 | 处置方式 | 🔴 危急 + 🟠 高危 | 🟡 中危 + 🟢 低危 |
| 应用本身 / 依赖软件 / 中间件 | 临时规避 | ⏰ 7 天内 | — (不强制临时规避) |
| 彻底整改 | ⏰ 3 个月内 | ⏰ 3 个月内 |
| 操作系统 / 数据库 / IT 基础设施 / 其它 | 临时规避 | ⏰ 15 天内 | — (不强制临时规避) |
| 彻底整改 | ⏰ 3 个月内 | 📋 择机处置 |
关键区分点:
- 应用/中间件 vs 操作系统/基础设施的 SLA 不同——应用层修复快(你自己的代码),基础设施修复慢(涉及补丁兼容性测试、停机窗口)
- "择机处置"不等于"不修"——需记录处置计划,在下一个维护窗口或版本升级时一并处理,且不得无限期推迟
- 临时规避仅针对危急+高危,中低危不要求临时规避但彻底整改时限不变
A.3 临时规避措施速查
危急/高危漏洞需在规定时限内完成临时规避(对外应用 48h / 对外基础设施 15d / 内部应用 7d / 内部基础设施 15d)。临时规避不等于修复,必须在 SLA 期限内完成彻底整改。
| 漏洞类型 | ✅ 可用的临时规避手段 | ❌ 不可接受的"规避" | ⚠️ 注意事项 |
| RCE / 命令注入 | 立即下线受影响功能;WAF 拦截恶意 payload;关闭相关端口 | 仅加日志监控不做拦截 | 最高优先级,宁可断服务不可被控 |
| SQL 注入 | WAF 拦截;数据库账户降权(移除 DROP/FILE/EXECUTE 权限);关闭受影响接口 | 仅前端加输入限制 | 降权不能替代参数化查询 |
| 未授权访问 | 加 IP 白名单/VPN 限制;紧急加认证中间件 | "内网不会被攻击" | 内网也需认证 |
| XSS(存储型) | WAF 拦截已知 payload;清除数据库中已存入的恶意内容;对输出临时 HTML 编码 | 仅拦截 <script> 标签 | 绕过方式多,WAF 只是缓冲 |
| SSRF | WAF 拦截内网 IP 段;出站防火墙白名单限制目标地址 | 仅拦截 127.0.0.1(可绕过) | DNS 重绑定可绕过 IP 黑名单 |
| 文件上传 WebShell | 立即删除已上传的恶意文件;临时关闭上传功能;Web 目录禁止执行 | 仅改文件扩展名限制 | 检查是否已被利用(查日志/后门) |
| 敏感信息泄露 | 关闭 debug 模式;移除泄露端点;加认证 | "已经泄露了,等修复吧" | 已泄露的密钥/凭证立即轮换 |
| 弱密码/默认凭证 | 立即修改所有默认密码;强制用户改密码 | 仅发邮件通知用户改密码 | 同步检查其他系统是否使用相同默认凭证 |
| 越权(IDOR/BOLA) | 受影响接口临时加权限校验中间件;限流降低利用速度 | 仅隐藏前端按钮/入口 | 前端隐藏不是安全控制 |
| CSRF | 受影响表单紧急加 CSRF Token;设 SameSite=Strict | 仅校验 Referer(可绕过) | 也检查关联的 API 接口 |
A.4 漏洞修复流程
| 阶段 | ✅ 必须做 | ❌ 禁止做 | 负责方 |
| 1. 确认 | 安全团队复现漏洞,确认影响范围、等级、受影响资产清单 | 未复现就定级为低危敷衍了事 | 安全团队 |
| 2. 通报 | 1 小时内通知系统负责人和研发负责人,创建漏洞工单 | 仅发邮件不跟踪;口头通知不留记录 | 安全团队 |
| 3. 规避 | 危急/高危按 A.2 时限完成临时规避(对外应用 48h / 基础设施 15d / 内部应用 7d),安全团队验证规避有效性 | 研发自己说"已规避"不经验证 | 研发 + 安全验证 |
| 4. 整改 | 研发完成代码级修复,提交代码评审,说明修复方案 | 仅靠 WAF 规则当作"已修复" | 研发团队 |
| 5. 验证 | 安全团队对修复后的代码/环境重新测试,确认漏洞已消除且无新引入问题 | 研发自测通过就关闭工单 | 安全团队 |
| 6. 关闭 | 验证通过后关闭工单;移除临时规避措施(如 WAF 特殊规则);更新漏洞台账 | 临时规避永久保留变成技术债 | 安全+研发 |
| 7. 复盘 | 危急/高危漏洞需做根因分析(Root Cause Analysis),输出同类问题排查方案 | 修完就忘,同类漏洞反复出现 | 安全+研发 |
A.5 超时升级机制
| 超时节点 | 升级动作 |
| 规避超时(超过 A.2 规定的临时规避时限) | 升级至部门技术负责人,对外危急/高危应用类考虑强制下线 |
| 整改超时 50%(对外应用超 15 天 / 内部应用超 45 天 / 基础设施超 45 天) | 升级至部门负责人,要求提交整改计划和延期理由 |
| 整改超时 100%(到期未修复) | 升级至分管领导,纳入绩效考核,系统降级处理 |
| 多次超时(同一系统 3 个月内 2 次以上超时) | 触发安全专项审计,暂停该系统新功能上线直至欠账清零 |
A.6 研发常见拒修理由
以下是实际工作中常见的"不修"理由,以及为什么这些理由不成立。
| 🙅 常见理由 | 📌 为什么不行 | ✅ 正确做法 |
| "这个漏洞利用条件很苛刻" | 攻击者有的是时间和工具,苛刻条件不等于不可利用。Log4Shell 利用条件也"苛刻"但全球沦陷 | 按评级修,不降级不拖延 |
| "内网系统没人攻击" | 内网是横向移动的主战场,一台被钓鱼就全线崩溃 | 内网系统同样按 SLA 修复 |
| "改了可能影响业务" | 不改被攻击了影响更大。做好测试和灰度发布 | 预留测试时间,不是不修的理由 |
| "等下个版本一起改" | 下个版本排期可能 3 个月后,漏洞不等你 | 紧急修复走 hotfix 分支,不依赖版本排期 |
| "WAF 已经拦截了" | WAF 是临时措施不是修复。WAF 规则可被绕过,也可能被误删 | WAF 规避 + 代码修复缺一不可 |
| "这个功能马上要下线了" | "马上"往往变成"永远不"。在下线之前仍有风险窗口 | 给出明确下线日期,超期仍需修复 |
| "我们加了监控" | 监控只能发现攻击,不能阻止攻击 | 监控 + 修复,不是二选一 |
| "复现不了/不是漏洞" | 研发环境和生产环境不同。安全团队已复现=漏洞确认 | 研发在生产等价环境复现,或信任安全团队的复现结果 |
A.7 漏洞修复质量检查清单
安全团队验证修复时,除了确认原始漏洞已消除,还需检查以下项。
| 检查项 | 说明 |
| 原始漏洞是否完全消除 | 用原始 PoC 和变体重新测试 |
| 是否修复了同一类型的所有实例 | 如 SQL 注入修了一个接口,其他接口是否也改了参数化查询 |
| 修复是否引入新的安全问题 | 如为修 XSS 加了全局过滤器,是否破坏了正常业务数据 |
| 修复方案是否为根本性修复 | 参数化查询(根本)vs 黑名单过滤(治标)。优先选前者 |
| 临时规避措施是否已清理 | WAF 特殊规则、临时 IP 白名单等是否已移除 |
| 泄露的凭证是否已轮换 | 如果漏洞导致密钥/Token/密码泄露,修漏洞的同时必须换掉已泄露的凭证 |
| 是否更新了安全配置基线 | 如修了默认密码问题,是否把"禁止默认密码"加入了部署检查清单 |