官方的翻译实在看不下去,2.1版本还没有翻译
这版是对比着2.0的中英文版本和2.1的英文版本翻译的,2.1删除了很多东西,我翻译的这般保留了一部分。不然有的地方很难看懂。
安全编码规范检查列表
输入验证
- 所有数据验证工作都应在受信任的系统(服务端而非客户端)上进行。
- 将数据来源其划分为“受信任”和“不受信任”两类。
- 必须验证所有来自不受信任来源的数据(如:数据库、文件流等)。
- 在整个应用程序中,使用集中式的输入验证机制。
- 为所有输入源指定正确的字符集,例如 UTF-8(规范化)。
- 在进行验证之前,先将数据编码为统一的字符集。
- 任何验证失败的情况,都应直接拒绝该输入。
- 如果系统支持 UTF-8 扩展字符集,必须在完成 UTF-8 解码之后再进行验证。
- 在处理之前,验证所有客户端提交的数据。
- 在处理数据之前,必须对所有客户端提交的数据进行验证,包括所有的参数、URL 以及 HTTP 头内容(比如 Cookie 的名称和值)。同时,不要遗漏由 JavaScript或其他前端脚本发起的请求。
- 核实协议的头部(Header)值仅包含 ASCII 字符。
- 验证来自重定向的数据,防止绕过前置逻辑。
- 验证数据是否符合预期的数据类型,使用白名单而非黑名单策略。
- 验证数据的取值范围。
- 验证数据的长度。
- 如果业务确实需要允许输入某些潜在的危险字符(如< > " ' % ( ) & + \ ' "),务必采取额外的安全控制措施。
- 如果标准的验证程序无法处理某些输入(如%00、%0d、%0a、\r、\n、../、..\),那么就需要进行额外的专项检查。
- 利用规范化处理来防御双重编码或其他形式的混淆攻击
输出编码
- 在受信任的系统(服务端而非客户端)上执行所有输出编码。
- 每一种类型的输出编码,都要使用成熟的、经过验证的标准库或函数
- 为所有的输出指定明确的字符集,例如 UTF-8。
- 对所有返回给客户端的、来自不受信任来源的数据,根据具体场景选择输出编码。
- 确保输出编码对所有目标系统安全。
- 当不可信数据要用于 SQL、XML 或 LDAP 查询时,必须根据上下文进行清洗(删除、替换、编码、转义)。
- 当不可信数据传递给操作系统命令时,必须进行清洗(删除、替换、编码、转义)。
身份验证和密码管理
- 除了专门设计为公开访问的页面和资源外,所有页面和资源都必须要求进行身份验证
- 所有的身份验证过程必须在可信系统上执行。
- 尽可能建立并使用标准的、经过测试的认证服务。
- 对所有认证控制措施采用集中式实现,包括调用外部认证服务的库。
- 将认证逻辑与请求的资源分离,并通过重定向机制与集中式认证控制进行交互。
- 无论什么原因导致身份认证失败都应拒绝访问。
- 所有系统管理功能和账户管理功能的安全性,必须至少与主认证机制一样高。
- 如果你的应用程序管理着一个凭证存储库,确保使用密码学上强健的、带盐值的单向哈希算法。
- 密码哈希必须在可信系统(服务端而非客户端)上实现。
- 仅在完成所有数据输入后才验证认证数据。
- 身份验证失败的响应消息,不应提示具体是哪一部分认证数据不正确。
- 为涉及敏感信息或功能的外部系统连接使用身份验证。
- 用于访问应用程序外部服务的认证凭证,应当存储在安全的存储库中。
- 仅使用 HTTP POST 请求传输认证凭据。
- 非临时密码必须通过加密连接或作为加密数据进行传输。
- 密码必须使用强密码,密码中必须包含大写字母、小写字母、数字和特殊字符,密码长度不能小于8个字符。
- 用户屏幕上的密码输入应当被遮蔽(例如HTML中input type="password")。
- 当连续多次登录失败后应强制锁定账户。
- 密码重置和更改操作需要与账户创建和认证同等级别的控制措施。
- 密码重置问题应支持足够随机的答案,不应使用公司名称、生肖/属相、生日等公开可查、答案集合有限、或能通过社会工程学获取的信息。
- 采用邮件方式进行密码重置时,仅限向预注册邮箱发送临时链接或密码。
- 临时密码和重置链接的有效期不能过长(推荐15~30分钟)。
- 当使用临时密码登录时,强制用户修改密码。
- 当发生密码重置时通知用户。
- 新密码不能与旧密码相同。
- 密码修改需至少间隔一天,以防范绕过旧密码校验的攻击。
- 根据规章制度的要求定期强制修改密码,修改间隔由管理员控制。
- 禁用登录页的“记住密码”功能。
- 用户成功登录时,应向用户展示该账户的上一次登录记录,包括:上次登录时间、ip地址、登录是否成功。
- 监控并防范密码喷洒攻击,即识别针对多个用户账户批量尝试同一常见密码的行为。
- 更改所有厂商提供的默认用户名和密码,或者禁用相关帐号。
- 在执行关键操作之前重新验证用户身份。
- 对高度敏感或高价值的交易账户使用多因素认证 (MFA)。
- 如果使用第三方代码进行认证,必须仔细检查其中是否存在恶意代码。
会话管理
以下内容中的“凭证”,泛指各类用于标识和验证用户身份的凭证,包括但不限于传统的 Session ID、JWT(JSON Web Tokens)以及 Authorization Header 中的各类 Token。
- 使用服务器或框架自带的会话管理控制机制。 应用程序应当仅将这些机制生成的凭证视为有效凭证。
- 凭证的创建必须始终在受信任的系统(服务端而非客户端)上进行。
- 会话管理控制应使用经过充分验证的算法, 以确保生成的凭证具有足够的随机性。
- 在设置带有凭证的 Cookie 时应该严格限定域(domain)和路径(path),不能让Cookie在整个网站或无关的路径下生效。
- 退出登录时应在服务端废除对应的凭证。
- 所有需要用户权限的页面都应提供退出登录功能。
- 建立会话不活动超时机制,在平衡安全风险与业务功能需求的前提下,将其设置得尽可能短。
- 禁止持久化登录,强制周期性终止活动会话。
- 如果在登录前已经建立了会话,登录成功后应关闭该旧会话并建立一个新会话。
- 每次重新认证时都应生成新的凭证。
- 禁止同一用户同时在多处登录。
- 不要在 URL、错误消息或日志中暴露凭证。
- 在服务器端实施适当的访问控制,防止服务器上其他用户未授权访问会话数据。
- 活动的会话应定期更换凭证并废除旧凭证。
- 身份认证过程中如果从 HTTP 协议切换至 HTTPS 协议,应该生成新的凭证。
- 应该统一使用 HTTPS,不应混用 HTTP 与 HTTPS 。
- 对于账号管理等敏感操作,应额外加上 CSRF Token 防护,每次会话(per-session)使用一个CSRF Token。
- 针对极高敏感度或核心业务操作,采用每次请求级别(per-request)的强随机令牌或参数进行校验。
- 为通过 TLS 连接传输的 Cookie 设置 "secure" 属性。
- 为 Cookie 设置 HttpOnly 属性,除非业务明确需要前端 JavaScript 读取或修改该 Cookie。
访问控制
- 仅使用可信的系统对象(例如服务端session对象)鉴权。
- 使用统一的全局组件做鉴权(例如 Java 的 Spring Security / Shiro)。
- 鉴权异常时,必须默认拒绝访问。
- 应用程序读取配置信息失败时,必须拒绝所有访问。
- 任何请求都必须鉴权,包括服务器端脚本发起的请求。
- 实现系统管理等特权功能的代码,应与常规业务代码隔离,单独实现。
- 严格限制各类敏感资源的访问权限,确保仅限授权用户/主体进行操作。管控范围必须全面覆盖以下对象:
- 应用层资源: 受保护的URL、业务功能、服务接口及直接对象引用;
- 数据与配置: 应用程序数据、用户/数据属性、访问控制策略及安全相关配置信息;
- 外部与非直控资源: 文件系统、云存储桶及第三方API等不受应用程序直接控制的资源。
- 用户调用接口的权限必须与前端页面所展示的权限一致。
- 如果状态数据必须存储于客户端,服务端应对数据加密和签名后再下发,以防范状态数据被篡改(例如 Shiro 框架中的 rememberMe Cookie)。
- 应用程序的执行必须严格遵守既定的业务流程。
- 限制单个用户或设备的操作频率,应该低到能防范自动化攻击,但不能过低影响正常业务。
- “Referer”请求头可以伪造,只能作为辅助性的安全检查手段,不能作为唯一的授权验证依据。
- 如果允许长时间保持认证会话,需定期重新验证用户的授权状态,以确保其权限未发生变更;若发生变更,应强制用户登出并重新进行身份认证。
- 实施账户审计,并强制禁用闲置账户。
- 当需要撤销用户权限时,应用程序必须支持禁用账户并终止相关会话。
- 用于连接外部系统或被外部系统连接的服务账户,应遵循最小权限原则。
- 制定《访问控制策略》,明确应用的业务规则、数据分类及授权标准与流程。通过文档化规范,确保权限配置准确受控,并清晰界定各类数据与系统资源的访问需求。
加密规范
- 所有用于保护应用用户机密的加密功能必须在受信系统(服务端而非客户端)上实现。
- 保护密钥,防止未授权访问。
- 加密模块应具备安全的故障处理机制。
- 系统生成随机数、随机文件名、随机 GUID 及随机字符串时,必须使用加密模块中经认证的随机数生成算法。
- 应用程序所使用的加密模块应满足 FIPS 140-2、GM/T 0028-2024 或其他同等标准的要求。
- 建立并实施加密密钥管理策略与流程。
错误处理和日志记录
- 不要在错误响应中泄露敏感信息,包括系统细节、会话标识符或账户信息。
- 错误处理程序不应显示调试信息或堆栈跟踪。
- 使用统一的错误提示信息,并使用自定义的报错页面。
- 应用程序应自行处理应用层面的错误,不能靠服务器配置处理。
- 异常发生时,须正确释放已分配内存,防止内存泄漏。
- 与安全控制相关的错误处理逻辑,默认应拒绝访问。
- 所有日志控制功能均应在受信任的系统(服务端而非客户端)上实现。
- 对于特定的安全事件,日志系统需要支持记录其成功与否。
- 确保日志中记录了重要事件数据,包括:时间戳、严重程度、区分标签(如果安全日志和普通日志混合记录)、引发事件的用户、源IP、结果(成功或失败)、事件描述。
- 确保包含不可信数据的日志条目,不会在日志查看界面或软件中被当作代码执行(防范日志注入)。
- 严格限制日志访问权限,仅限授权人员查看。
- 应使用统一的日志框架来处理所有的日志操作。
- 不要在日志中存储敏感信息,包括不必要的系统细节、会话标识符或密码。
- 应配备相应的工具或流程以便日志分析。
- 全面记录安全与系统事件,包括:
- 关键安全控制事件:包括所有身份验证尝试(尤其是失败情况)、访问控制失败、输入验证失败,以及使用无效或过期会话令牌的连接尝试。
- 系统异常与底层故障:涵盖所有系统级异常、后端 TLS 连接失败以及加密模块故障。
- 高危操作与篡改行为:包括所有管理功能操作(特别是安全配置的变更),以及明显的篡改事件(如状态数据的意外更改)。
- 使用密码学哈希函数来验证日志条目的完整性。
数据保护
- 落实最小权限原则,仅向用户提供完成其工作所必需的功能、数据和系统信息。
- 妥善保护服务器上存储的所有敏感数据缓存或临时副本,防止未授权访问;一旦这些临时工作文件不再需要,应立即予以清除。
- 对高度敏感的存储信息(如身份验证数据)进行加密,客户端和服务端都应加密。
- 防止用户下载服务器端的源代码。
- 严禁在客户端以明文或其他非密码学安全的方式存储密码、连接字符串及其他敏感信息。
- 删除用户可见代码中的注释,以免泄露后端系统或其他敏感信息
- 移除不必要的应用程序和系统文档,以防向攻击者暴露有用的信息。
- 禁止在 HTTP GET 请求参数中传递敏感信息。
- 禁用可能涉及敏感信息(包括账号密码等)的表单的自动填充功能。
- 禁止对包含敏感信息的页面启用客户端缓存。
- 当敏感数据不再需要时,应用程序应支持将其删除。
- 对服务器上存储的敏感数据实施适当的访问控制,包括缓存数据、临时文件以及仅限特定系统用户访问的数据。
通讯安全
- 必须对传输中的所有敏感信息进行加密。除了使用 TLS 保护网络连接外,还可以对敏感文件及非 HTTP 连接应用额外的独立加密手段。
- TLS 证书必须有效、域名匹配且未过期,必要时还需正确配置中间证书。
- TLS 连接失败时,不得降级到不安全的连接。
- 传输需要身份验证才能访问的内容以及其他各类敏感信息时,应使用 TLS 加密。
- 与涉及敏感信息或功能的外部系统建立连接时,应使用 TLS 加密。
- 统一采用单一、标准的 TLS 实现,并确保其配置得当。
- 为所有连接明确指定字符编码。
- 在链接到外部网站时,应过滤掉包含敏感信息的参数,防止其出现在 HTTP Referer 中。
系统配置
确保服务器、框架及系统组件运行的是最新批准版本。(很别扭,但是用最新稳定版本意思变了)
- 确保服务器、框架和系统组件已安装当前使用版本的所有补丁。
- 关闭目录列表功能。
- 遵循最小权限原则,严格限制 Web 服务器、进程及服务账号的权限。
- 当系统出现异常时,应以安全的方式终止或降级,避免产生安全漏洞。
- 移除所有不必要的功能和文件。
- 在部署前,务必删除测试代码及任何非生产环境所需的功能。
- 将不应公开的目录放入独立的父目录中,防止在 robots.txt 文件中暴露目录结构。
- 明确应用程序支持的 HTTP 方法(GET 或 POST),并确定不同页面是否需要采用差异化的处理方式。
- 禁用不必要的 HTTP 方法。
- 若 Web 服务器支持多个 HTTP 协议版本,需确保其配置方式保持一致,并充分理解各版本间的差异。
- 从 HTTP 响应头中移除与操作系统、Web 服务器版本及应用框架相关的非必要信息。
- 应用程序的安全配置信息应能够以人类可读的格式输出,以支持安全审计。
- 建立资产管理系统,并将系统组件和软件登记入册。
- 将开发环境与生产网络隔离,仅允许授权的开发和测试团队访问。
- 应建立软件变更控制系统,管理和记录开发与生产环境中的代码变更。
数据库安全
- 使用强类型的参数化查询。
- 做好输入验证与输出编码,并妥善处理元字符(包括" ' ; \ # `等);若验证或编码失败,拒绝执行数据库命令。
- 确保变量采用强类型定义。
- 应用程序访问数据库时,应遵循最小权限原则。
- 使用安全的凭证来访问数据库,禁止使用弱口令或硬编码在代码中的密码。
- 严禁在应用程序中硬编码连接字符串。连接字符串应存储在受信任系统的独立配置文件中,并且必须加密。
- 使用存储过程来访问和操作数据,控制数据库用户对存储过程的权限而非表的权限。
- 完成数据操作后应尽快关闭数据库连接。
- 修改或删除所有默认的数据库管理员密码。
- 关闭所有不必要的数据库功能。
- 清理不必要的系统默认内容(如示例数据库或示例表)
- 禁用所有非业务必需的默认账户。
- 应用程序应根据不同的信任级别,使用不同的凭证连接数据库(例如普通用户、只读用户、访客、管理员等)。
文件管理
- 禁止将用户输入直接用于动态包含函数。
- 上传文件前必须经过身份认证。
- 仅允许上传业务所必需的文件类型.
- 处理上传的文件时需要检查文件扩展名、文件头、文件内容(是否存在恶意代码),对于上传的图片需要二次渲染。
使用随机生成的名称(如 UUID)对上传的文件进行重命名,以防止文件被覆盖或发生路径篡改。(补充)
- 禁止将上传的文件保存在Web根目录中。
- 禁止或限制上传任何可能被 Web 服务器解析执行的文件(如 JSP、ASP、PHP 等动态脚本)。
- 关闭文件上传目录的执行权限。
- 在 UNIX 系统中实现安全的文件上传,应将目标文件目录挂载为逻辑驱动器,或使用 chroot 环境。
- 读取服务器上的文件时,必须用白名单检查文件名和类型。
- 禁止将用户输入用于动态重定向。
- 禁止直接传递文件或目录的路径。应使用 UUID 作为索引映射到预定义的路径列表。
- 禁止向客户端暴露绝对路径。
- 确保应用文件及资源设为只读。
- 对用户上传的文件进行病毒和恶意软件扫描。
内存管理
- 对不可信数据的输入和输出进行控制
- 检查缓冲区大小是否与指定要求一致
- 使用按字节数接收参数的函数时,确保正确处理 NULL 终止符
- 在循环中调用函数时,需检查缓冲区边界,防止溢出
- 将输入字符串传递给其他函数前,先将其截断至合理长度
- 必须显式释放资源,不要依赖垃圾回收机制
- 条件允许时,应使用不可执行栈
- 避免使用已知存在漏洞的函数
- 在函数执行完毕及所有退出点,正确释放已分配的内存
- 在函数的所有退出点,覆盖并清除已分配内存中存储的所有敏感信息
通用编码规范
- 优先使用带运行时安全保护的现代语言及其标准库。
- 调用系统内置的专用 API来执行操作系统任务。严禁应用程序直接向操作系统发送指令,尤其不要通过应用主动调起命令行终端(Shell)的方式来实现。
- 使用校验和或哈希算法,验证解释型代码、库文件、可执行文件及配置文件的完整性。
- 采用加锁机制防止多个请求同时并发,或使用同步机制以避免竞态条件(Race Conditions)。
- 保护共享变量和资源,防止不当的并发访问。
- 显式初始化所有变量及其他数据存储,无论是在声明时还是在首次使用前。
- 若应用程序必须以高权限运行,应尽可能延迟提权操作,并在完成后尽快降权。
- 深入理解编程语言的底层数据表示方式,以避免计算错误。
- 严禁将用户输入的数据传入任何动态执行函数中。
- 限制用户生成新代码或修改现有代码的权限。
- 全面审查所有附属应用、第三方代码及依赖库,以确认其业务必要性并验证其功能的安全性。
- 通过加密通道实现安全的更新机制。