👏 Hi! 我是 Yumuing,一个技术的敲钟人
👨💻 每天分享技术文章,永远做技术的朝拜者
📚 欢迎关注我的博客:Yumuing's blog
本文将从 XML 到 DTD 的相关概念的解析,再到两者之间的约束关系的说明,以及 XML 文件目前存在的安全漏洞相关分析,之后,同为数据传输工具的 YAML(YML)进行对比解释。
相关概念
XML 与其作用
独立于软件与硬件的信息传输工具
- 可扩展标记语言,与 HTML 语言存在类似点
- 一种数据传输的语法规范
- 主要是为了传输数据,而不是显示数据
- 标签没有预定义,需要自行定义标签
- XML 不会进行任何操作,仅仅只是把包装在 XML 标签内纯粹信息进行传输
- XML 不能独立传输和接受,必须编写相关程序才能传输、接受、显示 XML 文档
XML 仅仅只是一种结构化、存储及传输信息的传输规范并以纯文本文件形式存储,其标签的功能依赖于应用程序的特性。XML 是对 HTML 的一种补充,它不会替代 HTML ,毕竟 HTML 是用于格式化显示数据,与 XML 传输功能不存在替代关系。
目前 XML 支持的访问协议为:
在基本了解了 XML 究竟是什么样的数据传输工具之后,我们再来了解 XML 在数据传输方面的极大作用。
- 提供一套统一轻量化的数据传输标准,便于数据共享,完成对不兼容软件之间的数据传输
- XML 独立于软硬件及应用程序,让数据更具备普遍价值,而不需使用任何的转换程序
- 新型 Internet 语言是通过 XML 创建的,更有利于理解和创建新的 Internet 程序。
目前,XML 多用于应用程序的配置文件、充当小型数据库、传输数据、Web集成等等。
XML 与 DTD
XML 没有预定义相关标签限制,支持用户自定义数据内容。但也带来了一个语义规范的问题。什么样的 XML 文本 才是遵循规范的,更好地发挥良好的 XML 数据信息传输的功能。这就需要 DTD (Document TypeDefinition 文档类型定义)这一种 XML 约束文件进行 XML 验证。
DTD 文件中定义了这个文档中的根元素是什么,有几个子元素,每个子元素能出现几次,哪些元素有属性,属性的类型是什么,属性的默认值是什么等等,如果后面的XML内容中,与DTD中的定义不符,如元素个数不符、元素名称大小写不符等,那么XML文件解析时就会报错。
作用:
- 使用 DTD 确定收到的 XML 数据正确有效
- 不同组织可以使用一个通用的 DTD 来交换数据
XML 缺点与其安全漏洞
XML 也并不是绝对完美的,事物总是具备两面性的,它也存在一定的缺点,当然,没有对比的目标,具体的应用场景,任何事物的缺点将变得不那么明显,所以,需要具体场景具体分析其缺点,缺点如下:
- 以xml格式储存的数据要比以其他数据库格式储存占有的空间要大的多,因为它除了要保存原始数据外还需要保存元数据进行描述。
- 由于是采取树状存储,搜索效率较高,但插入与修改存在一定的效率问题。
- XML 是元置标记语言,任何个体与组织都能在此基础上制定自己的标准,这也造成了传输便利性的问题。
- 由于 XML 是一种标记语言,具备双向标签,在书写之时,需要注意标签对应关系,不得缺失,也较为麻烦。
- 需要花费大量代码来解析XML,不同浏览器之间解析XML的方式不一致,需要重复编写很多代码
- 安全性及并发操作机制缺失
XML 的安全漏洞大多可以分为两种:XML 注入、XXE 漏洞(外部实体安全漏洞)
XML注入是一种古老的技术,通过利用闭合标签改写XML文件实现的。
如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。这样会产生XML错误,利用这个错误就能进行 XML 注入
<?xml version="1.0" encoding="utf-8" ?>
<USER>
<user Account="admin">用户输入</user>
<user Account="root">root</user>
</USER>
<?若攻击者刚好能掌控用户输入字段,在用户输入区域输入
admin</user><user Account="hacker">hacker
更改 XML 尾部标签
<?最终修改结果为?>
<?xml version="1.0" encoding="utf-8" ?>
<USER>
<user Account="admin">admin</user>
<user Account="hacker">hacker</user>
<user Account="root">root</user>
</USER>
<?这样我们可以通过XML注入添加一个管理员账户
XML注入两大要素:标签闭合和获取XML表结构?>
除了以上的简单的 XML 注入,还可以利用部分可控的输入字段进行 XML 语句的拼接,实现对相关数据的查询等等,如 Xpath 注入。
那面对这样的 XML 注入攻击,在无法对用户输入进行过多的限制,我们将如何去进行防御呢?我们可以使用对输入字段进行数据过滤及 XML 相关字符进行转义即可。
XXE 注入也是 XML 注入的一部分,但相较于普通的 XML 注入,XXE 注入的攻击面更广,危害更大。XXE 注入(XML External Entity Injection) 全称为 XML 外部实体注入。
通过 XML 实体,”SYSTEM”关键词导致 XML 解析器可以从本地文件或者远程 URI 中读取数据。
XXE 这种攻击手段就是通过外部申明实体来完成的,基本的步骤如下:
- 外部申明 DTD 文件
- 书写相关规则文件
- 在 XML 文本中引入该文件
可能造成的危害:
读取任意文件
解析攻击者自定义 XML,赋值给根元素,利用 payload 等技术注入到 XML 文件中,从而将所赋值的根元素回显或发送数据给其他服务器 ,从而实现对文件的读取
执行系统命令
这种情况很少发生,但有些情况下攻击者能够通过 XXE执行代码,这主要是由于配置不当/开发内部应用导致的。如果我们足够幸运,并且PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上,就能远程执行代码。
探测内网端口
使用http URI并强制服务器向我们指定的端点和端口发送GET请求,将XXE转换为SSRF(服务器端请求伪造),根据响应时间/长度,攻击者将可以判断该端口是否已被开启。
攻击内网网站
构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。
面对 XXE 注入的防御方法基本分为两种:
- 配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD
- 使用开发语言提供的禁用外部实体的方法
- 过滤用户提交的 XML 数据
YAML 与 XML
YAML 作为一种比 XML 更为简单易读的序列化语言,正越来越多地被用于应用及配置文件的开发中。
YAML使用的是缩进来定义结构化数据。因此, 空格的多少决定了这部分数据所处的层级
它与 XML 相比来说,具备很多优点,如下:
可读性高
name: John Smith age: 35 Wife: name: Jane Smith age: 33 children: name: Kate Smith age: 10 name: Daniel Smith age 8
采用缩进方式表示层级,书写更为简单
与脚本语言的交互性更好
使用实现语言的数据类型
YML 也并不能完全取代 XML ,它也有一定的缺点,不能盲目执着的使用 YAML。如下:
- YAML 解析库并不统一,甚至也有一定缺失,将无法在大多数语言中解析出统一的结果
- YAML 对于大规模层级复杂的数据并不适用,缩进对应开始不够清晰
- YAML 默认是不安全的。加载用户提供的(不可信的)YAML 字符串需要仔细考虑