Abstract:
article_property.jsp 中的方法 _jspService() 向第 151 行的 Web 浏览器发送非法数据,从而导致浏览器执行恶意代码。
Explanation:
Cross-Site Scripting (XSS) 漏洞在以下情况下发生:
1. 数据通过一个不可信赖的数据源进入 Web 应用程序。对于 Persistent(也称为 Stored)XSS,不可信赖的源通常为数据库或其他后端数据存储,而对于 Reflected XSS,该源通常为 Web 请求。
在这种情况下,数据经由 SimpleHibernateDao.java 的第 276 行进入 execute()。
2. 未检验包含在动态内容中的数据,便将其传送给了 Web 用户。
在这种情况下,数据通过 article_property.jsp 的第 151 行中的 print() 传送。
传送到 Web 浏览器的恶意内容通常采用 JavaScript 代码片段的形式,但也可能会包含一些 HTML、Flash 或者其他任意一种可以被浏览器执行的代码。基于 XSS 的攻击手段花样百出,几乎是无穷无尽的,但通常它们都会包含传输给攻击者的私人数据(如 Cookie 或者其他会话信息)。在攻击者的控制下,指引受害者进入恶意的网络内容;或者利用易受攻击的站点,对用户的机器进行其他恶意操作。
示例 1:以下 JSP 代码片段可在数据库中查询具有给定 ID 的雇员,并通过 <c:out/> 标签输出相应雇员姓名。通过设置 escapeXml="false",该代码甚至不会对潜在的恶意数据执行基本的检查。
<%...
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from emp where id="+eid);
if (rs != null) {
rs.next();
String name = rs.getString("name");
}
%>
Employee Name: <c:out value="${name}" escapeXml="false"/>
如果对 name 的值处理得当,该代码就能正常地执行各种功能;如若处理不当,就会对代码的盗取行为无能为力。这段代码暴露出的危险较小,因为 name 的值是从数据库中读取的,而且显然这些内容是由应用程序管理的。然而,如果 name 的值是由用户提供的数据产生,数据库就会成为恶意内容沟通的通道。如果不对数据库中存储的所有数据进行恰当的输入验证,那么攻击者就可以在用户的 Web 浏览器中执行恶意命令。这种类型的 Persistent XSS(也称为 Stored XSS)盗取极其阴险狡猾,因为数据存储导致的间接性使得辨别威胁的难度增大,而且还提高了一个攻击影响多个用户的可能性。XSS 盗取会从访问提供留言簿 (guestbook) 的网站开始。攻击者会在这些留言簿的条目中嵌入 JavaScript,接下来所有访问该留言簿的用户都会执行这些恶意代码。
示例 2:以下 JSP 代码片段可从 HTTP 请求中读取雇员 ID eid,并通过 <c:out/> 标签将其显示给用户。通过设置 escapeXml="false",该代码甚至不会对潜在的恶意数据执行基本的检查。
Employee ID: <c:out value="${param.eid}" escapeXml="false"/>
如例 1 中所述,如果 eid 只包含标准的字母或数字文本,此代码就能正确运行。如果 eid 里有包含元字符或源代码中的值,那么 Web 浏览器就会像显示 HTTP 响应那样执行代码。
起初,这个例子似乎是不会轻易遭受攻击的。毕竟,有谁会输入导致恶意代码的 URL,并且还在自己的电脑上运行呢?真正的危险在于攻击者会创建恶意的 URL,然后采用电子邮件或者社会工程的欺骗手段诱使受害者访问此 URL 的链接。当受害者单击这个链接时,他们不知不觉地通过易受攻击的网络应用程序,将恶意内容带到了自己的电脑中。这种对易受攻击的 Web 应用程序进行盗取的机制通常被称为反射式 XSS。
有些人认为在移动世界中,典型的 Web 应用程序漏洞(如 cross-site scripting)是无意义的 -- 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源下载并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。
示例 3:以下代码在 Android WebView 中启用了 JavaScript(默认情况下,JavaScript 为禁用状态),并根据从 Android Intent 接收到的值加载页面。
...
WebView webview = (WebView) findViewById(R.id.webview); webview.getSettings().setJavaScriptEnabled(true); String url = this.getIntent().getExtras().getString("url"); webview.loadUrl(url);
...
如果 url 的值以 javascript: 开头,则接下来的 JavaScript 代码将在 WebView 中的 Web 页面上下文内部执行。
正如例子中所显示的,XSS 漏洞是由于 HTTP 响应中包含了未经验证的数据代码而引起的。受害者遭受 XSS 攻击的途径有三种:
- 如例 1 所述,应用程序将危险数据储存在一个数据库或其他可信赖的数据存储器中。这些危险数据随后会被回写到应用程序中,并包含在动态内容中。Persistent XSS 盗取发生在如下情况:攻击者将危险内容注入到数据存储器中,且该存储器之后会被读取并包含在动态内容中。从攻击者的角度看,注入恶意内容的最佳位置莫过于一个面向许多用户,尤其是相关用户显示的区域。相关用户通常在应用程序中具备较高的特权,或相互之间交换敏感数据,这些数据对攻击者来说有利用价值。如果某一个用户执行了恶意内容,攻击者就有可能以该用户的名义执行某些需要特权的操作,或者获得该用户个人所有的敏感数据的访问权限。
- 如例 2 所述,系统从 HTTP 请求中直接读取数据,并在 HTTP 响应中返回数据。当攻击者诱使用户为易受攻击的 Web 应用程序提供危险内容,而这些危险内容随后会反馈给用户并在 Web 浏览器中执行,就会发生反射式 XSS 盗取。发送恶意内容最常用的方法是,把恶意内容作为一个参数包含在公开发表的 URL 中,或者通过电子邮件直接发送给受害者。以这种手段构造的 URL 构成了多种“网络钓鱼”(phishing) 阴谋的核心,攻击者借此诱骗受害者访问指向易受攻击站点的 URL。站点将攻击者的内容反馈给受害者以后,便会执行这些内容,接下来会把用户计算机中的各种私密信息(比如包含会话信息的 cookie)传送给攻击者,或者执行其他恶意活动。
— 正如例 3 所示,应用程序之外的数据源将危险数据储存在一个数据库或其他数据存储器中,随后这些危险数据被当作可信赖的数据回写到应用程序中,并存储在动态内容中。
Instance ID: ABCA838BFAA09B579E48BD5903C92055
Priority Metadata Values:
IMPACT: 5.0
LIKELIHOOD: 4.8
Legacy Priority Metadata Values:
SEVERITY: 4.0
CONFIDENCE: 4.8
Remediation Effort: 1.0
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Recommendations:
针对 XSS 的解决方法是,确保在适当位置进行验证,并检验其属性是否正确。
由于 XSS 漏洞出现在应用程序的输出中包含恶意数据时,因此,合乎逻辑的做法是在数据流出应用程序的前一刻对其进行验证。然而,由于 Web 应用程序常常会包含复杂而难以理解的代码,用以生成动态内容,因此,这一方法容易产生遗漏错误(遗漏验证)。降低这一风险的有效途径是对 XSS 也执行输入验证。
由于 Web 应用程序必须验证输入信息以避免其他漏洞(如 SQL Injection),因此,一种相对简单的解决方法是,加强一个应用程序现有的输入验证机制,将 XSS 检测包括其中。尽管有一定的价值,但 XSS 输入验证并不能取代严格的输出验证。应用程序可能通过共享的数据存储或其他可信赖的数据源接受输入,而该数据存储所接受的输入源可能并未执行适当的输入验证。因此,应用程序不能间接地依赖于该数据或其他任意数据的安全性。这就意味着,避免 XSS 漏洞的最佳方法是验证所有进入应用程序以及由应用程序传送至用户端的数据。
针对 XSS 漏洞进行验证最安全的方式是,创建一份安全字符白名单,允许其中的字符出现在 HTTP 内容中,并且只接受完全由这些经认可的字符组成的输入。例如,有效的用户名可能仅包含字母数字字符,电话号码可能仅包含 0-9 的数字。然而,这种解决方法在 Web 应用程序中通常是行不通的,因为许多字符对浏览器来说都具有特殊的含义,在写入代码时,这些字符仍应被视为合法的输入,比如一个 Web 设计版就必须接受带有 HTML 代码片段的输入。
更灵活的解决方法称为黑名单方法,但其安全性较差,这种方法在进行输入之前就有选择地拒绝或避免了潜在的危险字符。为了创建这样一个列表,首先需要了解对于 Web 浏览器具有特殊含义的字符集。虽然 HTML 标准定义了哪些字符具有特殊含义,但是许多 Web 浏览器会设法更正 HTML 中的常见错误,并可能在特定的上下文中认为其他字符具有特殊含义,这就是我们不鼓励使用黑名单作为阻止 XSS 的方法的原因。卡耐基梅隆大学 (Carnegie Mellon University) 软件工程学院 (Software Engineering Institute) 下属的 CERT(R) (CERT(R) Coordination Center) 合作中心提供了有关各种上下文中认定的特殊字符的具体信息 [1]:
在有关块级别元素的内容中(位于一段文本的中间):
-“<”是一个特殊字符,因为它可以引入一个标签。
-“&”是一个特殊字符,因为它可以引入一个字符实体。
-“>”是一个特殊字符,之所以某些浏览器将其认定为特殊字符,是基于一种假设,即该页的作者本想在前面添加一个“<”,却错误地将其遗漏了。
下面的这些原则适用于属性值:
- 对于外加双引号的属性值,双引号是特殊字符,因为它们标记了该属性值的结束。
- 对于外加单引号的属性值,单引号是特殊字符,因为它们标记了该属性值的结束。
- 对于不带任何引号的属性值,空格字符(如空格符和制表符)是特殊字符。
-“&”与某些特定变量一起使用时是特殊字符,因为它引入了一个字符实体。
例如,在 URL 中,搜索引擎可能会在结果页面内提供一个链接,用户可以点击该链接来重新运行搜索。可以将这一方法运用于编写 URL 中的搜索查询语句,这将引入更多特殊字符:
- 空格符、制表符和换行符是特殊字符,因为它们标记了 URL 的结束。
-“&”是特殊字符,因为它可引入一个字符实体或分隔 CGI 参数。
- 非 ASCII 字符(即 ISO-8859-1 编码表中所有高于 128 的字符)不允许出现在 URL 中,因此在此上下文中也被视为特殊字符。
- 在服务器端对在 HTTP 转义序列中编码的参数进行解码时,必须过滤掉输入中的“%”符号。例如,当输入中出现“%68%65%6C%6C%6F”时,只有从输入的内容中过滤掉“%”,上述字符串才能在网页上显示为“hello”。
在 <SCRIPT> </SCRIPT> 的正文内:
- 如果可以将文本直接插入到已有的脚本标签中,应该过滤掉分号、省略号、中括号和换行符。
服务器端脚本:
- 如果服务器端脚本会将输入中的感叹号 (!) 转换成输出中的双引号 ("),则可能需要对此进行更多过滤。
其他可能出现的情况:
- 如果攻击者在 UTF-7 中提交了一个请求,那么特殊字符“<”可能会显示为“+ADw-”,并可能会绕过过滤。如果输出包含在没有确切定义编码格式的网页中,有些浏览器就会设法根据内容自动识别编码(此处采用 UTF-7 格式)。
一旦在应用程序中确定了针对 XSS 攻击执行验证的正确要点,以及验证过程中要考虑的特殊字符,下一个难点就是定义验证过程中处理各种特殊字符的方式。如果应用程序认定某些特殊字符为无效输入,那么您可以拒绝任何带有这些无效特殊字符的输入。第二种选择就是采用过滤手段来删除这些特殊字符。然而,过滤的负面作用在于,过滤内容的显示将发生改变。在需要完整显示输入内容的情况下,过滤的这种负面作用可能是无法接受的。
如果必须接受带有特殊字符的输入,并将其准确地显示出来,验证机制一定要对所有特殊字符进行编码,以便删除其具有的含义。官方的 HTML 规范 [2] 提供了特殊字符对应的 ISO 8859-1 编码值的完整列表。
许多应用程序服务器都试图避免应用程序出现 Cross-Site Scripting 漏洞,具体做法是为负责设置特定 HTTP 响应内容的函数提供各种实现方式,以检验是否存在进行 Cross-Site Scripting 攻击必需的字符。不要依赖运行应用程序的服务器,以此确保该应用程序的安全。开发了某个应用程序后,并不能保证在其生命周期中它会在哪些应用程序服务器中运行。由于标准和已知盗取方式的演变,我们不能保证应用程序服务器也会保持同步。
Tips:
1. HPE Security 安全编码规则包将就 SQL Injection 和 Access Control 提出警告:当把不可信赖的数据写入数据库时,数据库将出现问题,并且会将数据库当作不可信赖的数据的来源,这会导致 XSS 漏洞。如果数据库在您的环境中是可信赖的资源,则使用自定义筛选器筛选出包含 DATABASE 污染标志或来自数据库源的数据流问题。尽管如此,对所有从数据库中读取的内容进行验证仍然是较好的做法。
2. 虽然使用 URL 对不可信数据进行编码可以防止许多 XSS 攻击,但部分浏览器(尤其是 Internet Explorer 6 和 7 以及其他浏览器)在将数据传递给 JavaScript 解释器之前,会自动在文档对象模型 (DOM) 中的特定位置对其内容进行解码。为了反映出其危险之处,规则包不再认为 URL 编码例程足以防御 cross-site scripting 攻击。如果对数据值进行 URL 编码并随后输出,Fortify 将会报告存在 Cross-Site Scripting: Poor Validation 漏洞。
3. Fortify RTA adds protection against this category.
References:
[1] Understanding Malicious Content Mitigation for Web Developers, CERT,
http://www.cert.org/tech_tips/malicious_code_mitigation.html#9
[2] HTML 4.01 Specification, W3,
http://www.w3.org/TR/html4/sgml/entities.html#h-24.2
[3] Tongbo Luo, Hao Hao, Wenliang Du, Yifei Wang, and Heng Yin, Attacks on WebView in the Android System,
http://www.cis.syr.edu/~wedu/Research/paper/webview_acsac2011.pdf
[4] Erika Chin and David Wagner, Bifocals: AnalyzingWebView Vulnerabilities in Android Applications,
http://www.cs.berkeley.edu/~emc/papers/Chin-WISA-WebViews.pdf
[5] INJECT-3: XML and HTML generation requires care, Oracle,
http://www.oracle.com/technetwork/java/seccodeguide-139067.html#3
[6] INPUT-1: Validate inputs, Oracle,
http://www.oracle.com/technetwork/java/seccodeguide-139067.html#5
[7] Standards Mapping - Common Weakness Enumeration, CWE ID 79, CWE ID 80
[8] Standards Mapping - FIPS200, SI
[9] Standards Mapping - NIST Special Publication 800-53 Revision 4, SI-10 Information Input Validation (P1)
[10] Standards Mapping - OWASP Mobile Top 10 Risks 2014, M7 Client Side Injection
[11] Standards Mapping - OWASP Top 10 2004, A4 Cross Site Scripting
[12] Standards Mapping - OWASP Top 10 2007, A1 Cross Site Scripting (XSS)
[13] Standards Mapping - OWASP Top 10 2010, A2 Cross-Site Scripting (XSS)
[14] Standards Mapping - OWASP Top 10 2013, A3 Cross-Site Scripting (XSS)
[15] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1, Requirement 6.5.4
[16] Standards Mapping - Payment Card Industry Data Security Standard Version 1.2, Requirement 6.3.1.1, Requirement 6.5.1
[17] Standards Mapping - Payment Card Industry Data Security Standard Version 2.0, Requirement 6.5.7
[18] Standards Mapping - Payment Card Industry Data Security Standard Version 3.0, Requirement 6.5.7
[19] Standards Mapping - Payment Card Industry Data Security Standard Version 3.1, Requirement 6.5.7
[20] Standards Mapping - Payment Card Industry Data Security Standard Version 3.2, Requirement 6.5.7
[21] Standards Mapping - SANS Top 25 2009, Insecure Interaction - CWE ID 079
[22] Standards Mapping - SANS Top 25 2010, Insecure Interaction - CWE ID 079
[23] Standards Mapping - SANS Top 25 2011, Insecure Interaction - CWE ID 079
[24] Standards Mapping - Security Technical Implementation Guide Version 3.1, APP3510 CAT I, APP3580 CAT I
[25] Standards Mapping - Security Technical Implementation Guide Version 3.10, APP3510 CAT I, APP3580 CAT I
[26] Standards Mapping - Security Technical Implementation Guide Version 3.4, APP3510 CAT I, APP3580 CAT I
[27] Standards Mapping - Security Technical Implementation Guide Version 3.5, APP3510 CAT I, APP3580 CAT I
[28] Standards Mapping - Security Technical Implementation Guide Version 3.6, APP3510 CAT I, APP3580 CAT I
[29] Standards Mapping - Security Technical Implementation Guide Version 3.7, APP3510 CAT I, APP3580 CAT I
[30] Standards Mapping - Security Technical Implementation Guide Version 3.9, APP3510 CAT I, APP3580 CAT I
[31] Standards Mapping - Security Technical Implementation Guide Version 4.1, APSC-DV-002490 CAT I, APSC-DV-002560 CAT I
[32] Standards Mapping - Web Application Security Consortium 24 + 2, Cross-Site Scripting
[33] Standards Mapping - Web Application Security Consortium Version 2.00, Cross-Site Scripting (WASC-08)