摘要:对复现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 &amp; 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 "&#169;">
      ]>
      <author>&writer;&copyright;</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基础1.png

实例演示:

<?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的:

xml基础2.png

不使用CDATA的:

xml基础3.png

参考

DTD简介 - DTD教程™
XML DTD | 菜鸟教程
DTD 教程 | 菜鸟教程
DTD约束简介 - GordonDicaprio - 博客园
XML 验证器

文章目录