Windows .NET Core SDK权限提升漏洞分析

阅读量313249

|

发布时间 : 2020-08-25 15:30:33

x
译文声明

本文是翻译文章,文章原作者 itm4n,文章来源:itm4n.github.io

原文地址:https://itm4n.github.io/dotnet-sdk-eop/

译文仅供参考,具体内容表达以及含义原文为准。

 

0x00 概述

在DotNet Core Toolset安装程序中,存在一个奇怪的漏洞,该漏洞允许任何本地用户将其特权提升为SYSTEM。在这篇文章中,我将详细分析这个漏洞,尽管Microsoft没有将它认定为实际的漏洞,但是他们还是在暗中进行了(部分)修复。

 

0x01 背景介绍

2020年3月,Jonaslyk告诉我他在自己的计算机上遇到一个奇怪的错误。SYSTEM的PATH环境变量中似乎增加了与DotNet相关的路径。但奇怪的是,这个路径指向了非管理员用户的文件夹。基于此,我在自己的计算机上进行了检查,发现尽管存在与DotNet相关的路径,但它指向的是本地admin文件夹。如果用户拥有的文件夹的路径可以被附加到这个环境变量中,那么代码将可以以SYSTEM的身份来执行。因此,我们决定进行更深入的分析,看看最终能够实现什么。

 

0x02 初始设置

我们使用全新安装的Windows 10作为测试环境。在初始状态下,下面是SYSTEM帐户的PATH环境变量默认值。其中,S-1-5-18是LocalSystem帐户的安全标识符(SID)。

reg query "HKU\S-1-5-18\Environment" /v Path

然后,我们安装了Visual Studio Community 2019。安装过程中,我们选择包含.Net桌面开发组件。

点击“Install”按钮后,将下载并安装软件包。

由于我们需要寻找注册表项的修改情况,因此在这里使用Process Monitor来监视后台发生的事情。

在安装“.Net Core toolset”后,事情开始变得有趣。我们可以看到一个RegSetValue操作,是来自HKU\.DEFAULT\Environment\PATH中一个名为dotnet.exe的可执行文件。在这个事件之后,我们发现HKU\S-1-5-18\Environment中的PATH值与之前有所不同。

在这里,我们注意到存在两个潜在的问题:

1、变量%USERPROFILE%解析为当前用户的主文件夹,而不是SYSTEM帐户的主文件夹。

2、指向用户拥有的文件夹的另一个路径被添加到SYSTEM帐户的PATH中。

我们当前的用户还是本地管理员,因此这样的修改其影响非常有限。不过,理论上不应该发生这样的情况,因为这两个潜在的问题可能会产生意想不到的副作用(例如:UAC绕过)。

如果大家阅读过@RedVuln的《.Net系统持久性/绕过UAC/特权提升》这篇文章,可能会感觉这里的场景似曾相识。看上去,他几乎是在与我们相同的时间发现了这个问题。但我们还有一个疑问,因为DotNet SDK的安装需要一定的特权,所以是仅有管理员才能实现上述这个过程,还是普通用户也可以?

 

0x03 实际的特权提升漏洞

在上一章中,我们看到.Net SDK的安装过程对SYSTEM帐户的Path环境变量产生了一些潜在的意外后果。不过,严格来说,这并不会导致特权提升。

但是,如果我告诉大家,使用不具有管理员权限的普通用户身份登录时,也能够复现出同样的行为,这是不是意义就不一样了?

安装Visual Studio后,会将几个MSI文件复制到C:\Windows\Installer文件夹。由于我们观察到RegSetValue操作源自名为dotnet.exe的可执行文件,因此我们可以尝试在这些文件中搜索字符串。这是使用findstr命令得到的结果。

cd "C:\Windows\Installer"
findstr /I /M "dotnet.exe" "*.msi"

不错。我们找到了两个匹配的。接下来,可以尝试使用命令msiexec /qn /a <FILE>以普通用户身份运行每个文件,并观察注册表中SYSTEM帐户的环境Path变量。

在运行第一个MSI文件时,我们发现没有任何变化。但是,在运行第二个MSI文件时,我们观察到此时与以管理员身份安装DotNet SDK时发生的操作完全相同。

不过这一次,由于MSI文件是由用户lab-user运行的,因此路径C:\Users\lab-user\.dotnet\tools会附加到SYSTEM帐户的PATH环境变量中。因此,该用户现在可以植入DLL,并等待服务加载DLL,从而以SYSTEM身份执行代码。在Windows 10上,这个过程可以通过劫持由任务计划程序服务在启动时加载的WptsExtensions.dll来实现,@RedVuln在他的文章中曾进行过描述。

 

0x04 根本原因分析

这个漏洞的利用非常简单,因此我将重点放在根本原因分析上,这对于我们来说非常有趣。

问题是:我们从哪里开始?既然如此,不如从头开始,首先看看slightly_smiling_face

我们有一个Process Monitor转储文件,其中包含我们关注的RegSetValue事件。这是一个很好的起点,我们可以看看能够从栈跟踪里面学到什么。

我们可以看到,dotnet.exe可执行文件加载了几个DLL,然后加载了几个.Net程序集。

查看Process Start操作的详细信息,我们可以看到以下命令行:

"C:\Program Files\dotnet\\dotnet.exe" exec "C:\Program Files\dotnet\\sdk\3.1.200\dotnet.dll" internal-reportinstallsuccess ""

根据这个命令行,我们可以假设Win32 dotnet.exe可执行文件实际上是dotnet.dll程序集的包装,这个程序集有以下参数:internalreportinstallsuccess

因此,对其进行逆向,可以找到所有问题的答案:

1、可执行文件是如何评估.Net Core工具路径?

2、可执行文件如何在注册表中将路径添加到SYSTEM帐户的PATH?

为了检查程序集,我使用了dnSpy。实际上,这是我迄今为止在进行这类工作时最好用的工具。

程序的Main通过调用Program.ProcessArgs()开始。

这个函数有几个功能,其中最重要的部分我们以红色进行标记。

实际上,名称为ConfigureDotNetForFirstTimeUse()的函数看起来像是值得进一步分析的函数。

通过查看函数的内容,我们可以确认这一假设,因为我们开始看到一些对“环境路径”的引用。

根据依赖的操作系统,方法CreateEnvironmentPath()创建实现IEnvironmentProvider接口的对象的实例。因此,这里将是一个新的WindowsEnvironmentPath对象。

该对象基于动态生成的路径实例化,这个路径由某些字符串和“工具”的串联组成。

这个DotnetUserProfileFolderPath字符串本身是其他字符串和“.dotnet”的串联。

DotnetHomePath字符串是基于环境变量的值生成的。

变量的名称取决于PlateformHomeVariableName,由于操作系统是Windows,因此这里是USERPROFILE

总结之前的分析,我们知道DotNet工具的路径符合以下形式:<ENV.USERPROFILE>\.dotnet\tools,其中ENV.USERPROFILE的值由Environment.GetEnvironmentVariable()返回。到目前为止,这与我们在Process Monitor中观察到的一致,因此我们必须走上正确的道路。

如果查看Environment.GetEnvironmentVariable()的文档,可以了解到,默认情况下,如果未指定EnvironmentVariableTarget,则会从当前进程中检索这个值。

现在,如果再次查看Process Monitor中“Process Start”的详细信息,可以发现该进程使用了当前用户的环境,尽管该进程以NT AUTHORITY\SYSTEM的身份运行。因此,最终的工具路径解析为C:\Users\lab-user\.dotnet\tools

现在,我们知道了如何确定路径,因此就有了第一个问题的答案。接下来,需要找到这个路径的处理方式。
要回答第二个问题,可以返回Program.ConfigureDotNetForFirstTimeUse()方法,并查看在调用CreateEnvironmentPath()函数之后执行的操作。

确定工具路径后,将创建一个新的DotnetFirstTimeUseConfigurer对象,并立即调用Configure()方法。此时,路径信息存储在由pathAdder变量标识的EnvironmentPath对象中。

在这个方法中,相关的代码在下面的屏幕截图中以红色标示出,其中调用了AddPackageExecutablePath()方法。

这个方法很简单。在EnvironmentPath对象上调用AddPackageExecutablePathToUserPath()方法。

最后,AddPackageExecutablePathToUserPath()方法的内容为我们提供了第二个问题的答案。

首先,这个方法检查PATH环境变量的值,但是这次,使用一种稍有不同的方法进行检索。它使用附加的EnvironmentVariableTarget参数(设置为1)调用GetEnvironmentVariable

从文档中可以看出,如果将这个参数设置为1,则会从HKEY_CURRENT_USER\Environment注册表项中检索该值。当前用户为NT AUTHORITY\SYSTEM,这个值从HKU\S-1-5-18\Environment中检索。

问题在于,这同样也适用于SetEnvironmentVariable()方法。因此,C:\Users\lab-user\.dotnet\tools\将附加到注册表LOCAL SYSTEM帐户的路径环境变量之中。

总而言之,.Net Core工具集路径时基于当前用户的环境创建的,但由于该进程以NT AUTHORITY\SYSTEM的身份运行,因此已经应用到注册表中的LOCAL SYSTEM帐户,因此存在漏洞。

 

0x05 总结

这个漏洞的当前修复状态尚不清楚。由于没有得到Microsoft的官方认可,因此没有将该漏洞分配CVE ID。但是,正如前言中所述,Microsoft已经对这个漏洞进行部分修复。如果我们使用最新版本的.NET Core安装程序,C:\Users\<USER>\.dotnet\tools路径将不会再添加到路径中。

那么,如何确保计算机不受到这一漏洞影响呢?

首先,在注册表中检查以下值:

C:\Windows\System32>reg query HKU\S-1-5-18\Environment /v Path

HKEY_USERS\S-1-5-18\Environment
    Path    REG_EXPAND_SZ    %USERPROFILE%\AppData\Local\Microsoft\WindowsApps;

如果我们看到实际内容与上面显示的内容有所不同,则可以以管理员身份使用以下命令来恢复默认值:

C:\Windows\System32>reg ADD HKU\S-1-5-18\Environment /v Path /d "%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;" /F
The operation completed successfully.

然后,我们可以更新Visual Studio或.Net SDK,并再次检查注册表。“tools”文件夹应该不会再存在。
遗憾的是,根据我的最新测试,%USERPROFILE%变量仍然解析为当前用户的“home”文件夹。这意味着,在安装.Net SDK时,路径仍然会更改。值得庆幸的是,这个文件夹不能用于本地特权提升,因为相应的文件夹属于管理员所有。

 

0x06 参考资料

[1] .Net系统持久性/绕过UAC/特权提升 https://redvuln.com/net_privesc/
[2] dnSpy https://github.com/0xd4d/dnSpy

本文翻译自itm4n.github.io 原文链接。如若转载请注明出处。
分享到:微信
+10赞
收藏
P!chu
分享到:微信

发表评论

内容需知
合作单位
  • 安全客
  • 安全客
Copyright © 北京奇虎科技有限公司 三六零数字安全科技集团有限公司 安全客 All Rights Reserved 京ICP备08010314号-66