脚本注入漏洞是 Web 应用程序开发的一大难题:其原因和补救措施看似简单,但在大规模 Web 开发中却出人意料地难以预防。
XSS(跨站脚本)2,7,8 漏洞的产生是由于 Web 应用程序中数据验证、清理或转义不足,导致攻击者可以在应用程序的上下文中执行恶意 JavaScript 脚本。这段注入的代码随后可以利用受害者的权限执行攻击者想做的任何事情。利用 XSS 漏洞会导致受害者与易受攻击应用程序的会话完全(但不一定是持久地)被入侵。本文概述了 XSS 漏洞是如何产生的,以及为什么在实际的 Web 应用程序软件开发中如此难以避免它们。然后,本文介绍了谷歌开发的用于解决此问题的软件设计模式。这些设计模式的一个关键目标是将 XSS 漏洞的潜在范围限制在应用程序代码库的一小部分,从而显著提高人们对不存在此类安全漏洞的推断能力。在谷歌的几个软件项目中,这种方法已显著降低了 XSS 漏洞的发生率。
最常见的情况是,XSS 漏洞是由于对来自不可信来源的字符串进行不充分的验证、清理或转义,并将这些字符串传递到接收器,接收器以可能导致脚本执行的方式解释它们。
不可信数据的常见来源包括 HTTP 请求参数,以及位于持久性数据存储中的用户控制数据。字符串通常在赋值给接收器之前与更大的字符串连接或插入到更大的字符串中。与 XSS 漏洞最相关的常见接收器是那些将赋值解释为 HTML 标记的接收器,其中包括 MIME 类型为text/html的服务器端 HTTP 响应,以及Element.prototype.innerHTMLDOM(文档对象模型)8 属性在浏览器端 JavaScript 代码中。
图 1a 显示了一个假设的照片共享应用程序中易受攻击的代码片段。与许多现代 Web 应用程序一样,其大部分用户界面逻辑是在浏览器端 JavaScript 代码中实现的,但本文中提出的观察结果很容易转移到通过传统服务器端 HTML 渲染实现 UI 的应用程序。
在图中的代码片段 (1) 中,应用程序生成 HTML 标记,用于在另一个用户邀请第一个用户查看相册时向其显示通知。生成的标记被赋值给 DOM 元素的innerHTML属性(浏览器窗口中 UI 元素的层次对象表示中的节点),从而导致其评估和渲染。
该通知包含相册的标题,由第二个用户选择。恶意用户可以创建一个标题为
<script>attackScript;</script>
的相册。由于没有应用转义或验证,因此这个由攻击者选择的 HTML 会按原样插入到代码片段 (1) 中生成的标记中。此标记被赋值给innerHTML接收器,因此在受害者的会话上下文中进行评估,执行攻击者选择的 JavaScript 代码。
要修复此漏洞,相册的标题在使用在标记中之前必须进行 HTML 转义,以确保它被解释为纯文本,而不是标记。HTML 转义会替换 HTML 元字符,例如<, >, ", '<、> 和 " 以及&&与相应的字符实体引用或数字字符引用, <, >, '<、> 和 " 以及"&
。然后,结果将被解析为文本节点或属性值中的子字符串,并且不会引入元素或属性边界。
如前所述,大多数具有 XSS 潜在风险的数据流都流入将数据解释为 HTML 标记的接收器。但是,其他类型的接收器也可能导致 XSS 漏洞:图 1b 显示了前面提到的照片共享应用程序的另一个代码片段,负责在登录操作后导航用户界面。在全新登录后,应用程序会导航到应用程序主页的预配置 URL。但是,如果登录是由会话超时引起的,则应用程序会导航回用户在超时之前访问的 URL。Web 应用程序中用于短期状态存储的常用技术是,此 URL 编码在当前 URL 的参数中。页面导航是通过赋值给window.location.hrefDOM 属性来实现的,浏览器将其解释为将当前窗口导航到提供的 URL 的指令。不幸的是,将浏览器导航到表单的 URLjavascript:attackScript
会导致 URL 的主体作为 JavaScript 执行。在这种情况下,目标 URL 是从当前 URL 的参数中提取的,这通常在攻击者的控制之下(受害者访问的恶意页面可以指示浏览器导航到攻击者选择的 URL)。因此,这段代码也容易受到 XSS 攻击。要修复此漏洞,有必要验证 URL 在取消引用时不会导致脚本执行,方法是确保其方案是良性的,例如.
为什么 XSS 如此难以避免?
在实践中,避免在重要的应用程序中引入 XSS 是一个难题:根据 OWASP(开放 Web 应用程序安全项目)的数据,XSS 仍然是 Web 应用程序中最常见的漏洞之一;4 在谷歌内部,它是谷歌漏洞奖励计划 (https://www.google.com/about/appsecurity/reward-program/) 下报告的最常见的 Web 应用程序漏洞类别。
传统上,关于如何预防 XSS 的建议(包括我自己的)主要集中在
• 培训开发人员处理(通过清理、验证和/或转义)插入到 HTML 标记中的不可信值。2,5
• 安全审查和/或测试代码,以确保遵守此类指南。
细微的安全考量
复杂、难以推断的数据流
回想一下,XSS 是由不可信、未经验证/转义的数据流入容易注入的接收器而产生的。为了断言应用程序中不存在 XSS 漏洞,安全审查员必须首先找到所有此类数据接收器,然后检查周围的代码,以确保传输到接收器的数据具有上下文适当的验证和转义。当遇到缺少验证和转义的赋值时,审查员必须向后追溯此数据流,直到可以确定以下情况之一
• 该值完全在应用程序控制之下,因此不会导致攻击者控制的注入。
• 该值已在某个地方沿途经过验证、转义或以其他方式安全构建。
• 该值实际上未经过正确验证和转义,并且可能存在 XSS 漏洞。innerHTML让我们检查一下图 1a 代码片段 (1) 中流入接收器的数据流。为了说明目的,需要调查的代码片段和数据流以红色显示。由于未对sharedAlbum.title应用转义,因此我们将它的来源追溯到持久性存储中的albums
实体 (4),通过 Web 前端代码 (2)。然而,这不是数据的最终来源——相册名称以前是由另一个用户输入的(即,起源于不同的时间上下文)。由于从最终的不可信来源到现在的整个流程中,此值在任何地方都没有应用转义,因此产生了 XSS 漏洞。页面导航是通过赋值给类似的考虑适用于图 1b 中的数据流:在赋值给 (5)
之前没有立即进行验证,因此有必要进行回溯。在代码片段 (6) 中,代码探索分支:在 true 分支中,该值源自数据存储 (3) 中的配置实体,通过 Web 前端 (8);此值可以假定为应用程序控制且可信,并且可以安全使用,无需进一步验证。值得注意的是,持久性存储在同一模式的不同实体中包含可信和不可信数据——不能对存储数据的来源做出笼统的假设。页面导航是通过赋值给在 else 分支中,URL 源自当前 URL 的参数,从
许多犯错的机会
图 1a 和 1b 仅显示了一个假设的 Web 应用程序的两个小片段。实际上,一个大型、重要的 Web 应用程序将有数百甚至数千个分支和合并的数据流流入容易注入的接收器。如果开发人员在验证或转义方面犯了错误,则每个此类数据流都可能导致 XSS 漏洞。
探索所有这些数据流并断言不存在 XSS 对于安全审查员来说是一项艰巨的任务,特别是考虑到正在积极开发的项目的代码库不断变化。使用启发式方法静态分析代码库中数据流的自动化工具可以提供帮助。然而,我们在谷歌的经验表明,它们并没有实质性地提高基于审查的评估的信心,因为它们的推理必然是不完整的,并且容易出现误报和漏报。此外,它们与人工审查员在推理跨多个系统组件、使用各种编程语言、RPC(远程过程调用)机制等的全系统数据流方面也面临类似的困难,并且涉及跨数据存储的多个时间上下文的数据流。
模板系统能否拯救?
在实践中,HTML 标记以及其中的插值点通常使用 HTML 模板 来指定。模板系统公开了用于渲染 HTML 标记的特定领域语言。HTML 标记模板从模板变量中导出 HTML 标记字符串的函数。
图 1c 说明了 HTML 标记模板 (9) 的使用:此示例在照片共享应用程序中渲染用户个人资料,包括用户名、个人博客站点的超链接以及允许用户表达任何特殊兴趣的自由文本。
一些模板引擎支持自动转义,其中转义操作会自动插入到模板中每个插值点周围。大多数模板引擎的自动转义工具都是非上下文的,并且不加区分地应用 HTML 转义操作,但不考虑特殊的 HTML 上下文,例如 URL、CSS 和 JavaScript。
上下文自动转义模板引擎6 推断每个模板替换的上下文所需的必要验证和转义操作,因此考虑了此类特殊上下文。上下文自动转义模板系统的使用大大降低了 XSS 漏洞的可能性:在 (9) 中,将不可信值profile.name和profile.blogUrl
替换到生成的标记中不会导致 XSS——模板系统会自动推断所需的 HTML 转义和 URL 验证。
但是,在未使用模板的代码(如图 1a (1) 所示)或涉及非 HTML 接收器的代码(如图 1b (5) 所示)中,仍然可能出现 XSS 漏洞。此外,开发人员有时需要免除某些替换的自动转义:在图 1c (9) 中,profile.aboutHtml
的转义被显式抑制,因为该字段被假定为包含用户提供的消息,其中包含简单的、安全的 HTML 标记(以支持在“关于我自己”用户个人资料字段中使用字体、颜色和超链接)。此外,开发人员有时需要免除某些替换的自动转义:在图 1c (9) 中,不幸的是,存在一个 XSS 漏洞:
可靠地预防 XSS 漏洞的引入
我们在谷歌安全团队的经验表明,代码检查和测试不能以合理的置信度确保大型 Web 应用程序中不存在 XSS 漏洞。当然,检查和测试都提供了巨大的价值,并且通常会在应用程序中发现一些漏洞(甚至可能是大多数漏洞),但很难确定它们是否发现了所有漏洞(甚至几乎所有漏洞)。
我们能做得更好吗?我们认为是这样的。在过去的几年中,谷歌的安全工程师开发了实用的软件设计模式,与当前的做法相比,这些模式使 Web 应用程序的开发更能够抵御无意中在应用程序代码中引入 XSS 漏洞。
这种方法的主要目标是将可能导致 XSS 漏洞的代码限制在应用程序代码库的很小一部分。
第二个同等重要的目标是提供与现有开发人员工作流程相比不会增加不可接受程度的摩擦的开发人员体验。
这种方法的关键组成部分是
• 固有安全的 API。易受注入攻击的 Web 平台和 HTML 渲染 API 被封装在旨在固有安全地防止 XSS 的包装器 API 中,因为使用此类 API 不会导致 XSS 漏洞。
• 安全类型契约。定义了特殊类型,其契约规定其值在特定上下文中可以安全使用,无需进一步转义和验证。
固有安全的 API
我们的目标是为易受注入攻击的浏览器端 Web 平台 API 接收器以及服务器端和客户端 HTML 标记渲染提供固有安全的包装器 API。
对于某些 API,这很简单。例如,图 1b (5) 中易受攻击的赋值可以用 JavaScript Closure Library 提供的固有安全包装器 API 来替换,如图 2b (5') 所示。包装器 API 在运行时验证提供的 URL 是无方案 URL 还是具有已知良性方案的 URL。
使用安全包装器 API 可确保此代码不会导致 XSS 漏洞,而与赋值 URL 的来源无关。至关重要的是,(5') 中的代码及其扇入 (6-8) 都不需要检查 XSS 漏洞。这种好处的代价非常小,即运行时验证,如果(且仅当)采用第一个分支,则运行时验证在技术上是不必要的——即使从配置存储获得的 URL 实际上是一个可信值,它仍然会得到验证。
严格上下文自动转义模板引擎
为 HTML 渲染设计固有安全的 API 更具挑战性。目标是设计 API,以保证在受信任 HTML 标记中每个数据替换点,数据都经过适当的验证、清理和/或转义,除非可以证明特定数据项基于其来源或先前的验证、清理或转义,可以安全地在该上下文中使用。
这些固有安全的 API 是通过将上下文自动转义模板引擎6 的概念加强为 SCAETE(严格上下文自动转义模板引擎)来创建的。本质上,SCAETE 对模板代码施加了两个额外的约束
• 不允许使用禁用或修改自动推断的上下文转义和验证的指令。
安全类型契约以刚刚描述的形式,SCAETE 不考虑模板参数旨在在没有验证或转义的情况下使用的情况,例如图 1c 中的aboutHtml
——SCAETE 无条件地验证和转义所有模板参数,并且不允许使用指令来禁用自动转义机制。
此类用例通过类型来解决,这些类型的契约规定其值在相应的 HTML 上下文中可以安全使用,例如“内部 HTML”、超链接 URL、可执行资源 URL 等。类型契约是非正式的:如果已知某个值已通过验证、清理、转义或以保证其在类型的目标上下文中使用不会导致攻击者控制的脚本执行的方式构建,则该值满足给定的类型契约。这是否确实如此,是通过专家基于对 Web 平台相关行为的专业知识8,对创建此类类型值的代码进行专家推理来确定的。正如将要看到的,此类安全敏感代码封装在少量专用库中;应用程序代码使用这些库,但不依赖自身来正确创建此类类型的实例,因此无需进行安全审查。
以下是在使用中的类型和类型契约的示例•SafeHtml
以下是在使用中的类型和类型契约的示例。SafeHtml 类型的值,转换为字符串后,在用作 HTML 标记时不会导致攻击者控制的脚本执行。SafeUrl
以下是在使用中的类型和类型契约的示例。当用作超链接 URL 时,此类型的值不会导致攻击者控制的脚本执行。TrustedResourceUrl。此类型的值可以安全地用作可执行资源或“控制”资源的 URL,例如<script>元素的src
属性,或 CSS 样式表的源。本质上,此类型承诺其值是资源本身是可信的 URL。
这些类型实现为包含底层字符串值的简单包装器对象。类型成员资格通常无法通过运行时谓词来建立,类型安全审查的工厂方法和构建器的责任是保证它们产生的任何实例的类型契约。类型成员资格可以基于处理(例如,验证或清理)、构造和来源,或其组合。
SCAETE 使用安全契约来指定免除自动转义:如果替换值是其契约支持其在替换的 HTML 上下文中安全使用的类型,则该值不受运行时转义的约束。•由 SCAETE 处理的模板会生成函数,这些函数保证发出不会导致 XSS 的 HTML 标记,前提是模板参数遵守其安全契约(如果适用)。实际上,应用 SCAETE 导出的模板函数的结果本身就满足
类型契约。图 2c 显示了 SCAETE 和安全类型契约在图 1c 代码片段中的应用。模板 (9) 的严格上下文转义不允许使用noAutoescape以刚刚描述的形式,SCAETE 不考虑模板参数旨在在没有验证或转义的情况下使用的情况,例如图 1c 中的指令。但是,简单地删除它将启用此值的自动转义,但在这种情况下,这是不需要的。相反,我们将profile对象的•字段更改为具有
未检查的转换•当然,最终我们需要创建•由 SCAETE 处理的模板会生成函数,这些函数保证发出不会导致 XSS 的 HTML 标记,前提是模板参数遵守其安全契约(如果适用)。实际上,应用 SCAETE 导出的模板函数的结果本身就满足
类型的所需值。在示例中,持久性存储中的相应字段包含可能由攻击者恶意提供的 HTML 标记。将此不可信标记通过 HTML 清理器,以删除任何可能导致脚本执行的标记,使其可以安全地在 HTML 上下文中使用,从而生成满足•为了实际创建这些类型的值,提供了未检查的转换工厂方法,这些方法使用任意字符串并返回给定包装器类型的实例(例如,。SafeHtml 类型的值,转换为字符串后,在用作 HTML 标记时不会导致攻击者控制的脚本执行。或
),而不应用任何运行时清理或转义。
必须仔细地对每次使用此类未检查的转换进行安全审查,以确保在所有可能的程序状态下,传递给转换的字符串都满足生成的类型契约,这基于特定于上下文的处理或构造。因此,应尽可能少地使用未检查的转换,并且仅在可以轻松推断其用于安全审查目的的场景中使用。
编码指南
为了使这种方法有效,必须确保开发人员永远不会编写直接调用可能容易注入攻击的接收器的应用程序代码,并且他们改为使用相应的安全包装器 API。此外,它必须确保以可审查性为目标设计未检查转换的用途,并且实际上已对其进行了安全审查。这两个约束代表了应用程序代码库的所有代码都必须遵守的编码指南。
根据我们的经验,即使在中等规模的项目中,也必须强制执行编码指南——否则,违规行为肯定会随着时间的推移而蔓延。在谷歌,我们使用开源错误易发静态检查器1 (https://code.google.com/p/error-prone/),它集成到谷歌的 Java 工具链中,并且是谷歌开源 Closure Compiler (https://developers.google.com/closure/compiler/) 的一项功能,用于白名单 JavaScript 中特定方法和属性的使用。由使用“禁止”API 引起的错误包括对相应安全 API 文档的引用,建议开发人员如何解决该错误。通过谷歌分布式构建系统提供的包可见性机制3,强制执行对未检查转换用途的审查要求。
如果工具链集成的检查不可用,则可以通过更简单的类似 lint 的工具来强制执行编码指南。
在照片共享示例中,此类检查将对图 1a-1c 中对innerHTMLprofile.namelocation.href的赋值引发错误,并将建议开发人员改为使用相应的固有安全 API。对于赋值给innerHTML,这通常意味着使用严格模板替换 HTML 标记的临时连接,由模板系统的运行时直接渲染到 DOM 元素中,如图 2a 所示。
重新审视示例应用程序的代码片段,在它们符合编码指南后显示(图 2a-2c),容易注入攻击的数据接收器的用途已替换为相应的固有安全 API,如 (1')、(5')、(9') 和 (10') 所示。现在,这些代码片段都不会导致 XSS 漏洞,并且在安全审查期间不需要检查它们及其扇入。
唯一剩下的需要安全代码审查的代码部分(除了 SCAETE、其运行时和 API 包装器库的实现等基础设施代码之外)是HtmlSanitizer包 (12''),特别是包本地扇入到•的未检查转换。此转换的正确性仅依赖于 HTML 清理器的正确性,并且可以单独对该包进行安全审查和测试。如果一个库在多个应用程序之间共享,则其审查成本会在用户之间分摊。
当然,这种方法可以提供的保证存在局限性:首先,安全审查员可能会遗漏代码的安全相关部分(模板系统、标记清理器等)中的错误;其次,应用程序代码可能会使用反射等结构,从而违反我们依赖的类型的封装;最后,某些类别的 XSS 漏洞(在实践中相对罕见)无法通过通用应用的上下文数据验证和转义来解决,正如我们的设计模式所确保的那样, 这些漏洞需要在 Web 应用程序框架的其他层或在各个 Web 应用程序的设计中解决。8
将图 1a-1c 中的易受攻击的代码片段与图 2a-2c 中的安全对应片段进行比较表明,我们的方法不会对开发人员工作流程施加重大更改,也不会对代码进行重大更改。例如,在图 2b (5') 中,我们只是使用安全包装器而不是“原始”Web 平台 API;否则,此代码及其扇入保持不变。
编码指南确实要求开发人员使用安全 API 来生成 HTML 标记,例如图 2a (1') 中的严格模板。但是,作为回报,使用此类 API 可以防止 XSS 漏洞,并大大减轻开发人员考虑和显式指定转义和数据验证的负担。
只有在图 2c 中,才需要对应用程序进行更重要的更改:以刚刚描述的形式,SCAETE 不考虑模板参数旨在在没有验证或转义的情况下使用的情况,例如图 1c 中的字段的类型从String更改为•,并且此类型的使用通过 RPC 从后端贯穿到前端。即使在这里,所需的更改也相对有限:字段类型的更改以及在后端代码 (12') 中添加对HtmlSanitizer库的调用。
这种情况在典型的 Web 应用程序中往往很少见。在绝大多数用途中,自动运行时验证和转义在功能上是正确的:流入用户界面标记的大多数数据流值(包括应用程序控制的和用户输入派生的)都倾向于表示纯文本、常规http/httpsURL 以及其他可以干净地验证和/或转义的值。
这种设计模式已应用于谷歌使用的多个开源和专有 Web 应用程序框架和模板引擎:已将对严格上下文自动转义的支持添加到 Closure Templates (https://developers.google.com/closure/templates/)、AngularJS (https://docs.angularjs.org/api/ng/service/$sce) 以及谷歌专有模板系统。谷歌的安全工程师和基础设施开发人员还实现了诸如•, 。SafeHtml 类型的值,转换为字符串后,在用作 HTML 标记时不会导致攻击者控制的脚本执行。等类型库,并在 Google Web Toolkit (https://gwt.java.net.cn/doc/latest/DevGuideSecuritySafeHtml.html)、JavaScript Closure Library (https://developers.google.com/closure/library/) 以及各种谷歌专有库和框架中添加了固有安全的 API。
很难得出关于任何特定漏洞预防方法影响的精确统计数据:我们的设计模式可以防止 XSS 漏洞从一开始就被引入,但我们不知道如果不使用它们,会引入多少漏洞。
但是,我们可以根据随着时间的推移采用我们方法的现有大型项目中的漏洞计数进行观察。此类观察结果只能被视为轶事,因为漏洞计数可能受到许多变量的影响,例如代码大小和复杂性、与安全相关的开发人员教育等。尽管如此,观察结果表明,我们的方法显着促进了 XSS 漏洞的显着减少。
谷歌旗舰应用程序的几个开发团队采用了这些设计模式和编码指南。他们建立了静态强制措施,规定所有 HTML 标记都由严格上下文自动转义模板生成,并且他们禁止直接使用某些容易注入攻击的 Web 平台 API,例如innerHTML.
其中一个最大、最复杂的应用程序,在 Closure Templates 语言中使用了 1,000 多个 HTML 模板,于 2013 年初迁移到严格自动转义。在 2012 年全年(迁移之前),谷歌的漏洞跟踪器中针对此应用程序提交了 31 个 XSS 漏洞。迁移后,在 2014 年年中之前的这一年中,仅提交了 4 个 XSS 漏洞,而在 2014 年上半年根本没有提交任何漏洞。对于另一个大型应用程序(也使用了 1,000 多个模板),其迁移仍在进行中,在同一时间段内,XSS 漏洞从 21 个减少到 9 个。
即使没有完全遵守编码指南,也可以实现一些好处:随着符合规范的代码比例增加,可能导致漏洞的代码比例缩小,并且对不存在漏洞的信心增加。虽然几乎没有理由不完全按照指南编写新代码,但如果重构成本超过收益,并且如果我们已经通过其他方式(例如,强化审查和测试)对该代码的安全性充满信心,我们可以选择不重构某些现有代码。
软件设计可用于将 XSS 漏洞的潜在范围隔离到应用程序代码库的很小一部分。这使得对代码的这些部分进行深入的安全审查和测试变得切实可行,从而高度确信整个 Web 应用程序不易受到 XSS 漏洞的影响。我们的方法实际适用于大型、复杂、真实的 Web 应用程序,并且已导致多个开发项目中的 XSS 漏洞显着减少。
这种解决从根本上来说是一个涉及全系统数据流的难题的方法,包含两个关键原则
• 基于在典型的 Web 应用程序中,保守地运行时转义和验证流入容易注入的接收器的大多数数据在功能上是正确的这一观察,我们选择将所有字符串类型的值都视为可能不可信,并受运行时验证和转义的约束,而与其来源无关。这种设计选择完全避免了在典型的 Web 应用程序中对绝大多数全系统数据流进行全程序推理的需要。
• 仅在默认运行时验证和转义在功能上不正确的情况下,我们才使用类型契约来传达某些值在给定上下文中已经可以安全使用。这种类型的使用允许对全系统数据流进行组合推理,并允许安全专家基于包本地推理隔离审查安全关键代码。
我们的编码指南对应用程序代码施加了一些约束(尽管它们通常只需要对现有代码进行有限的更改)。相比之下,许多现有的 XSS 预防和检测方法旨在适用于现有的、未经修改的代码。此要求使问题变得更加困难,并且通常需要使用复杂的全程序静态和/或动态数据流分析技术。有关此领域现有工作的概述,请参阅 Mike Samuel 等人6。放宽此要求消除了对专用工具和技术(例如运行时污点跟踪或全程序静态分析)的需求,使我们能够完全依赖软件设计、可通过非常简单的静态检查强制执行的编码指南、现有的语言原生类型系统以及对现有上下文自动转义模板系统的小幅增强的组合。因此,我们的方法可以用于以各种编程语言编写的应用程序,而无需对工具链、构建系统或运行时环境提出特殊要求。
以下代码片段旨在用超链接(HTML 锚元素)的标记填充 DOM 元素
anchor 元素的 click 事件处理程序(当用户点击此 UI 元素时,浏览器会调用该处理程序)被设置为调用一个 JavaScript 函数,并将以下值作为参数:category在插入到 HTML 标记之前,以下值category使用来自 JavaScript Closure Library 的转义函数进行 HTML 转义。此外,在插入到'onclick\'处理程序的 JavaScript 表达式中的字符串字面量之前,还会对其进行 JavaScript 字符串字面量转义(替换onclick为鲜花 & 植物对于变量category,生成的 HTML 标记是
那么 bug 在哪里呢?考虑以下category的值
将此值传递给htmlEscape会得到
当评估此标记时,浏览器将首先对onclick属性的值进行 HTML 反转义,然后再将其作为 JavaScript 表达式进行评估。因此,被评估的 JavaScript 表达式会导致执行攻击者的脚本
createCategoryList('');attackScript();//')
因此,潜在的 bug 非常微妙:程序员调用了适当的转义函数,但顺序错误。
1. Aftandilian, E., Sauciuc, R., Priya, S., Krishnan, S. 2012. Building useful program analysis tools using an extensible Java compiler. International Working Conference on Source Code Analysis and Manipulation (SCAM): 14-23.
2. Daswani, N., Kern, C., Kesavan, A. 2007. Foundations of Security: What Every Programmer Needs to Know. Apress.
3. Morgenthaler, J. D., Gridnev, M., Sauciuc, R., Bhansali, S. 2012. Searching for build debt: experiences managing technical debt at Google. Third International Workshop on Managing Technical Debt (MTD): 1-6.
4. OWASP. 2013. Top 10 List; https://www.owasp.org/index.php/Top_10_2013-Top_10.
5. OWASP. 2014. XSS (cross site scripting) prevention cheat sheet; https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet.
6. Samuel, M., Saxena, P., Song, D. 2011. Context-sensitive auto-sanitization in Web templating languages using type qualifiers. Proceedings of the 18th Conference on Computer and Communications Security: 587-600.
7. Su, Z. Wassermann, G. 2006. The essence of command injection attacks in web applications. POPL '06. http://dl.acm.org/citation.cfm?id=1111070
8. Zalewski, M. 2011. The Tangled Web: A Guide to Securing Modern Web Applications. No Starch Press.
喜欢还是讨厌?请告诉我们
Christoph Kern ([email protected]) 是 Google 的信息安全工程师。他的主要工作是设计 API 和框架,使开发人员能够轻松编写安全软件,并消除或降低开发人员意外引入安全漏洞的风险。
© 2014 1542-7730/14/0700 $10.00
最初发表于 Queue vol. 12, no. 7—
在 数字图书馆 中评论本文
Paul Vixie - 要么静态,要么回家
当前和历史上计算机与网络安全的大多数问题都可以归结为一个简单的观察:让其他人控制我们的设备对我们不利。在另一个时间,我将解释“其他人”和“不利”的含义。就本文而言,我将完全专注于“控制”的含义。我们失去设备控制的一种方式是外部分布式拒绝服务 (DDoS) 攻击,这种攻击用不需要的流量填充网络,不给真实(“需要”)的流量留下空间。其他形式的 DDoS 类似:例如,低轨道离子炮 (LOIC) 的攻击可能不会完全填满网络,但它可以使 Web 服务器忙于响应无用的攻击请求,以至于服务器无法响应任何有用的客户请求。
Axel Arnbak, Hadi Asghari, Michel Van Eeten, Nico Van Eijk - HTTPS 市场中的安全崩溃
HTTPS(安全超文本传输协议)已发展成为安全 Web 浏览的事实标准。通过基于证书的身份验证协议,Web 服务和互联网用户首先使用 TLS/SSL 证书相互验证身份(“握手”),端到端加密 Web 通信,并在浏览器中显示挂锁,以指示通信是安全的。近年来,HTTPS 已成为保护在线社交、政治和经济活动的重要技术。
Sharon Goldberg - 为什么保护互联网路由需要这么长时间?
BGP(边界网关协议)是将互联网粘合在一起的粘合剂,使不同组织运营的大型网络之间能够进行数据通信。BGP 通过为组织之间的流量设置路由来使互联网通信全球化——例如,从波士顿大学的网络,通过更大的 ISP(互联网服务提供商),如 Level3、巴基斯坦电信和中国电信,然后到住宅网络,如 Comcast 或企业网络,如美国银行。
Ben Laurie - 证书透明度
2011 年 8 月 28 日,一个为 google.com 错误颁发的通配符 HTTPS 证书被用于对伊朗的多个用户进行中间人攻击。该证书由一家荷兰 CA(证书颁发机构)DigiNotar 颁发,DigiNotar 是 VASCO Data Security International 的子公司。后来的分析表明,DigiNotar 早在一个多月前就意识到了其系统中的漏洞——至少从 7 月 19 日开始。它还表明,至少颁发了 531 个欺诈性证书。最终计数可能永远不会知道,因为 DigiNotar 没有所有错误颁发证书的记录。