跳转至

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) strcpystrcatsprintf无长度限制 栈/堆/缓冲区溢出
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 = userInputdocument.write(userInput) DOM XSS
V3.2.3 JS变量用let/const声明;不在document上存全局变量;做命名空间隔离 document.xxx = data;隐式全局变量 DOM Clobbering
编号 ✅ 必须做 ❌ 禁止做 🛡️ 防御
V3.3.1 所有Cookie加Secure标记。Cookie名用__Host-__Secure-前缀 Cookie不设Secure;通过HTTP明文传输 Cookie劫持
V3.3.2 按用途设置SameSite:认证Cookie用StrictLax;跨站需要的用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-urireport-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-ForX-Real-IPX-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-EncodingContent-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的nbfexp 不验证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/urandomSecureRandomcrypto.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.51PHP/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/密码泄露,修漏洞的同时必须换掉已泄露的凭证
是否更新了安全配置基线 如修了默认密码问题,是否把"禁止默认密码"加入了部署检查清单