C3:验证所有输入并处理异常
描述
输入验证是一种编程技术,确保只有格式正确的数据才能进入软件系统组件。当注入攻击针对客户端(例如基于 JavaScript 的攻击)时,Web 服务器可以在将攻击者提供的数据转发给客户端之前对其进行引用/编码。
注入攻击通常发生在应用程序将输入数据误认为是可执行命令时,并且在忘记或错误实施输入验证时也经常发生。例如,假设一个 Web 应用程序接受用户输入的电子邮件地址。电子邮件地址将是预期的“数据”。攻击者现在寻找方法来混淆应用程序,使其将这些(假定的)数据作为命令执行。不同的注入攻击针对不同的区域。
- 当攻击者欺骗应用程序将用户输入(数据)解释为 SQL 命令(或其一部分)时,就会发生 SQL 注入攻击。被注入的命令在数据库服务器内执行。
- 远程命令注入 (RCE) 发生在应用程序将用户数据与在 Web 应用程序服务器/主机上执行的命令混淆时。服务器端模板注入是应用程序服务器内执行的注入的另一个示例。
- 当发生 JavaScript 注入时,Web 应用程序已接受用户数据,但被强制将该数据作为代码执行。注入的 JavaScript 代码通常在另一个用户的 Web 浏览器中执行,因此不直接攻击 Web 服务器,而是攻击其他用户。
语法和语义有效性
应用程序在使用数据之前(包括将其显示回用户),应检查数据的**语法**和**语义**是否有效(按此顺序)。
-
**语法有效性**意味着数据采用预期格式。例如,应用程序可能允许用户选择一个四位数的“帐户 ID”来执行某些操作。应用程序应假定用户正在输入 SQL 注入有效载荷,并检查用户输入的数据长度是否恰好为四位数字且仅由数字组成(除了使用适当的查询参数化)。
-
**语义有效性**包括只接受在应用程序功能和上下文的可接受范围内的输入。例如,在选择日期范围时,开始日期必须在结束日期之前。
威胁
- 攻击者可以通过提交恶意输入来操纵数据库查询,从而利用 SQL 注入漏洞,可能获得对敏感数据的未经授权的访问。
- 攻击者可以通过向网页注入恶意脚本来执行跨站脚本 (XSS) 攻击,这些脚本随后在其他用户的浏览器中执行,可能窃取会话令牌或个人信息。
- 攻击者可以通过将恶意命令注入系统调用或 API 来远程执行任意代码,可能控制目标系统。
- 攻击者可以通过提供超出预期长度的输入来触发缓冲区溢出错误,可能覆盖内存并执行任意代码。
- 攻击者可以通过使用格式错误或过多的输入来使系统超载,从而发起拒绝服务攻击,可能导致合法用户无法使用服务。
- 攻击者可以通过路径遍历攻击访问未经授权的文件和目录,可能暴露敏感系统文件或配置数据。
- 攻击者可以将恶意载荷插入 XML 文档以利用 XML 解析漏洞,可能导致信息泄露或系统受损。
- 攻击者可以将恶意模板注入服务器端模板引擎,可能在服务器上实现远程代码执行。
- 攻击者可以通过 HTTP 参数污染攻击混淆应用程序并绕过安全控制,可能操纵应用程序逻辑或访问受限功能。
实施
针对注入攻击的保护通常基于纵深防御方法,并结合了输入过滤、输出转义和强化机制的利用。前两者仅取决于已实施的安全措施,而后者主要取决于客户端支持,例如,在防范 XSS 时,从输入中过滤 XSS 并对服务器端输出数据进行转义将无论使用何种 Web 浏览器都能防止 XSS;添加内容安全策略 (Content-Security-Policy) 可以防止 XSS,但前提是用户的浏览器支持它。因此,安全绝不能仅依赖于可选的强化措施。
防止恶意数据进入系统
永远不要信任提供的数据!筛选所有数据以查找恶意模式,或者更好的是,根据允许列表检查所有数据。
白名单 vs 黑名单
执行语法验证有两种通用方法,通常称为允许列表和拒绝列表。
- 拒绝列表或**拒绝列表验证**试图检查给定数据是否不包含“已知不良”内容。例如,Web 应用程序可能会阻止包含精确文本 `