xml基础
摘要:对复现xxe漏洞用到的xml语法进行记录
说明
XML 指可扩展标记语言(eXtensible Markup Language)。
XML 被设计用来传输和存储数据。
XML 很重要,也很容易学习。
XML文档格式
- XML 文档必须有一个根元素
- XML元素都必须有一个关闭标签
- XML 标签对大小写敏感
- XML 元素必须被正确的嵌套
- XML 属性值必须加引号,这里引号用法和python类似
第一个例子
<?xml version = "1.0" encoding = "UTF-8" ?>
<address>
<name>Tanmay Su</name>
<company>Yiibai Yiibai</company>
<phone>(086) 123-4567-789</phone>
</address>
vrsion="1.0"说明是xml的版本号是1.0,encoding="UTF-8"说明文档编码为utf-8。<address>为根元素,<name>、<company>、<phone>为子元素。
第二个例子
<?xml version = "1.0" encoding = "UTF-8" ?>
<address>
<person>
<name>Tanmay Su</name>
<company>Yiibai Yiibai</company>
<phone>(086) 123-4567-789</phone>
</person>
<person>
<name>Tanmay</name>
<company>Yiibai</company>
<phone>(086) 666-6666-666</phone>
</person>
</address>
根元素为<address>代表一个地址表,子元素有两个<person>元素代表两个人,<person>元素里面的子元素描述这个人的特征。
XML 元素必须遵循以下命名规则:
- 名称可以包含字母、数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字母 xml(或者 XML、Xml 等等)开始
- 名称不能包含空格
- 可使用任何名称,没有保留的字词。
xml文档格式
XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。注意:<?xml version="1.0"?> 必须放在文档的第一行。
<?xml version="1.0"?><!--XML申明-->
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,head,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素里面的内容为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素面的内容为为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素面的内容为为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素面的内容为为”#PCDATA”类型-->
]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。例如 文档元素中to,from,head,body和声明时候的顺序一样
DTD文档类型定义
貌似浏览器对xml文档的要求只要符合xml文档格式,不检测是否符合DTD,所以下面看看就好。
DTD主要的功能我感觉就只有两个:
- 对xml文档元素的内容类型进行定义
- 定义实体
对xml文档元素的内容类型进行定义
<?xml version="1.0"?><!--XML申明-->
<!--文档类型定义-->
<!DOCTYPE NEWSPAPER [
<!ELEMENT NEWSPAPER (ARTICLE+)> <!--NEWSPAPER NEWSPAPER为xml中的根元素,+号说明最少有一个ARTICLE子元素-->
<!ELEMENT ARTICLE (HEADLINE,BYLINE,LEAD,BODY,NOTES)> <!--ARTICLE元素下面必须有HEADLINE、BYLINE等五个子元素-->
<!ELEMENT HEADLINE (#PCDATA)> <!--HEADLINE元素中的类型可以是PCDATA,也可以是普通文本-->
<!ELEMENT BYLINE (#PCDATA)>
<!ELEMENT LEAD (#PCDATA)>
<!ELEMENT BODY (#PCDATA)>
<!ELEMENT NOTES (#PCDATA)> <!--HEADLINE元素中的类型必须是普通文本-->
<!ATTLIST ARTICLE AUTHOR CDATA #REQUIRED> <!--ARTICLE元素必须有AUTHOR属性,而且AUTHOR的属性必须为CDATA类型-->
<!ATTLIST ARTICLE EDITOR CDATA #IMPLIED> <!--ARTICLE元素可以有EDITOR属性,也可以没有-->
<!ATTLIST ARTICLE DATE CDATA #IMPLIED>
<!ATTLIST ARTICLE EDITION CDATA #IMPLIED>
]>
<NEWSPAPER>
<ARTICLE AUTHOR="xiaogang" EDITOR="wangwu">
<HEADLINE>xxxx</HEADLINE>
<BYLINE>xxxx</BYLINE>
<LEAD>xxx</LEAD>
<BODY>xxx</BODY>
<NOTES>xxx</NOTES>
</ARTICLE>
</NEWSPAPER>
dtd如何使用
文档类型定义(DTD)可定义合法的XML文档构建模块,它使用一系列合法的元素来定义文档的结构。DTD 可
被成行地声明于XML文档中(内部引用),也可作为一个外部引用。
实体可以理解为变量,其必须在DTD中定义申明,可以在文档中的其他位置引用该变量的值。
内部声明DTD:
<!DOCTYPE 根元素 [元素声明]>
举例:
<!DOCTYPE tutorials [ <!ELEMENT tutorials (tutorial)+> <!ELEMENT tutorial (name,url)> <!ELEMENT name (#PCDATA)> <!ELEMENT url (#PCDATA)> <!ATTLIST tutorials type CDATA #REQUIRED> ]>
引用外部DTD:
<!DOCTYPE 根元素 SYSTEM "文件名">
举例1:
<!DOCTYPE tutorials SYSTEM "tutorials.dtd">
举例2:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
关键字PUBLIC:表示它是公共DTD(用于公共分发)。
URL的存在:表明这是一个外部DTD(DTD在位于URL的文档中定义)。
标识符表示:正式的公共标识符,在使用公共DTD时是必需的,浏览器首先通过标识符寻找,如果找不到就通过url寻找。
两者都有
<!DOCTYPE rootname SYSTEM URL [DTD]>
关键字SYSTEM:表示它是私有DTD(不适用于公开发布)。
URL和[DTD]的存在:表明即引用了外部DTD又声明了外部DTD
(DTD的一部分在位于URL的文档中定义,另一部分在XML文档中定义)。
举例:
<!DOCTYPE tutorials SYSTEM "tutorials.dtd" [ <!ELEMENT tutorial (summary)> <!ELEMENT summary (#PCDATA)> ]>
DTD文档中有很多重要的关键字如下:
- DOCTYPE(DTD的声明)
- ENTITY(实体的声明)
- SYSTEM、PUBLIC(外部资源申请)
实体的使用
1.实体类型:
第一种分类方式:
根据实体类型分。内置实体 (Built-in entities)
<?xml version = "1.0"?> <note> <description>I'm a technical writer & programmer</description> <note>
字符实体 (Character entities)
<?xml version = "1.0" encoding = "UTF-8" standalone = "yes"?> <!DOCTYPE author[ <!ELEMENT author (#PCDATA)> <!ENTITY writer "Max Su"> <!ENTITY copyright "©"> ]> <author>&writer;©right;</author>
注意到使用©作为版权特征的值。 将此文件另存为sample.xml并在浏览器中打开它,将看到版权被字符©替换。
常规实体 (General entities)
举例1:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY name "bmjoker">] > <foo> <value>&name;</value> </foo>
举例2:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY content SYSTEM "file:///etc/passwd">]> <foo> <value>&content;</value> </foo>
参数实体 (Parameter entities)
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY % name SYSTEM "file:///etc/passwd"> %name; ]>
第二种分类方式:
如果在DTD之外声明实体,则称为外部实体。如果在DTD中声明实体,则称为内部实体。内部实体
举例1:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY name "bmjoker">] > <foo> <value>&name;</value> </foo>
举例2:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY content SYSTEM "file:///etc/passwd">]> <foo> <value>&content;</value> </foo>
外部实体
举例1:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a SYSTEM "file:///www/admin/localhost_80/wwwroot/test.dtd"> <a>&ename;</a>
以下是DTD文件test.dtd 的内容
<!ENTITY ename "entity_value">
2.外部实体在DTD中使用
由于xxe漏洞主要是利用了DTD引用外部实体导致的漏洞,那么重点看下能引用哪些类型的外部实体。
<!ENTITY 实体名称 SYSTEM "URI">
语法引用外部的实体,而非内部实体,那么URL中能写哪些类型的外部实体呢?
主要的有file、http、https、ftp等等,当然不同的程序支持的不一样:
实例演示:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY content SYSTEM "file:///etc/passwd">]>
<foo>
<value>&content;</value>
</foo>
CDATA
XML CDATA
XML 文档中的所有文本均会被解析器解析。
只有 CDATA 区段中的文本会被解析器忽略。
PCDATA - 被解析的字符数据
XML 解析器通常会解析 XML 文档中所有的文本。
当某个 XML 元素被解析时,其标签之间的文本也会被解析:
<message>This text is also parsed</message>
解析器之所以这么做是因为 XML 元素可包含其他元素,就像这个实例中,其中的 <name> 元素包含着另外的两个元素(first 和 last):
<name><first>Bill</first><last>Gates</last></name>
而解析器会把它分解为像这样的子元素:
<name>
<first>Bill</first>
<last>Gates</last>
</name>
解析字符数据(PCDATA)是 XML 解析器解析的文本数据使用的一个术语。
CDATA - (未解析)字符数据
术语 CDATA 是不应该由 XML 解析器解析的文本数据。
像 "<" 和 "&" 字符在 XML 元素中都是非法的。
"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。
"&" 会产生错误,因为解析器会把该字符解释为字符实体的开始。
某些文本,比如 JavaScript 代码,包含大量 "<" 或 "&" 字符。为了避免错误,可以将脚本代码定义为 CDATA。
CDATA 部分中的所有内容都会被解析器忽略。
CDATA 部分由 "<![CDATA[" 开始,由 "]]>" 结束:
<?xml version = "1.0" encoding = "UTF-8" ?>
<address>
<name>Tanmay Su</name>
<company>Yiibai Yiibai</company>
<phone>(086) 123-4567-789</phone>
<name>
<![CDATA[
<address>
<name>Tanmay Su</name>
<company>Yiibai Yiibai</company>
<phone>(086) 123-4567-789</phone>
</address>
]]>
</name>
</address>
使用CDATA的:
不使用CDATA的:
参考
DTD简介 - DTD教程™
XML DTD | 菜鸟教程
DTD 教程 | 菜鸟教程
DTD约束简介 - GordonDicaprio - 博客园
XML 验证器
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。