RPC,全称“Remote Procedure Call”,即远程过程调用,它并不是Windows独有的概念,RPC的第一个实现是在unix上;RPC在Windows上的设计是一种强大、健壮、高效且“安全”的进程间通信 (IPC) 机制,它支持数据交换和调用驻留在不同进程中的功能。不同的进程可以在同一台机器上、局域网上或互联网上。简单说它允许请求操作另一台计算机上的服务,而无需了解背后的详细信息。
RPC的通讯架构如下图:
这个协议在历史上已经有很多有趣的发现,从各种Abuse到RCE以及LPE,在红队项目的内网渗透中频频出现。
作为渗透测试人员,尽量了解更多的目标内部网络情况是再好不过的,得到的各类信息能够帮助确认潜在的风险。
通过IOXIDResolver接口的ServerAlive2方法可以让我们无需认证直接获取对应主机的网卡信息。
这也是安全测试过程中比较常用的用来确定是否存在“双网卡”主机的方式。
epmapper (MS-RPC EndPoint Mapper),是RPC架构中的一个服务之一,负责列出公开接口;它会将服务映射到端口。我们可以通过列出的公开接口,来探测对应主机上的应用服务,如使用Impacket中的rpcdump.py即可获取接口的UUID。
如某安全防护软件会在epmapper服务中注册一个接口:
通过rpcdump.py探测该机器发现存在此UUID:
所以此类工具就可以探测目标主机是否存在此款防护软件,同样的可以扩展到探测是否存在其他的在epmapper注册过接口的主机应用程序。
如SentineOne EDR
MS-RPC服务还可以通过不同的传输协议访问,其中通过SMB传输的RPC服务可以通过命名管道访问,可以对某些机器进行SMB空会话连接的话(比较少见)还可以使用更多RPC接口搜集信息,这也导致了可以利用这个特点进行一些信息的探测。
常见的情况是如果红队人员在目标内网有一个落脚点以及得到一份域凭据就可以使用这种方式连接DC进行一些RPC接口调用,从而探测有价值的域信息;使用该种方法比执行一些NET类收集命令有更好的规避性。
Samba Suite中提供了一个工具:rpcclient,它是执行客户端 MS-RPC 功能的工具。
rpcclient [-A authfile] [-c <command string>] [-d debuglevel] [-l logdir] [-N] [-s <smb config file>] [-U username[%password]] [-W workgroup] [-I destinationIP] {server}
rpcclient支持以下类别的RPC调用:LSARPC,LSARPC-DS,REG,SRVSVC,SAMR,SPOOLSS,NETLOGON,FSRVP,可以进行多个方面的信息搜集,以下几个例子:
获取域信息:
获取权限:
还可以枚举RID、创建用户、枚举域用户、探测内网出网情况等等。
MS-SAMR,该协议支持包含用户和组的帐户存储或目录的管理功能。该协议的目标是使 IT 管理员和用户能够管理用户、组和计算机。如协议所述,MS-SAMR可以进行一切用户、用户组的相关操作,其中一些功能在安全测试中可以帮助红队人员更好的开展工作。
MS-SAMR中的SamrChangePasswordUser或者SamrSetInformationUser可以用来修改用户的密码,这在域渗透中使用比较频繁,因为在拿下域控服务器后可能我们想要登录Exchange服务器或是其他域认证的应用系统,但只知道对应用户的hash,这样的话我们就可以使用这种方式修改已知的明文密码登录系统后再修改回原始hash,具体的利用工具有mimikatz以及Impacket中的smbpassword.py。
在安全测试中,添加用户往往关键点在于如何绕过防护软件,从开始的使用net1.exe绕过到参数欺骗、使用NetUserAddAPI添加用户,而NetUserAdd这些API更为底层的实现就是MS-SAMR,我们也可以直接调用该MS-SAMR对应的接口实现添加用户的程序,从而达到更好的规避防护的效果。
在安全测试中,遇到登录机器提示密码过期时,也可以通过MS-SAMR来直接通过旧密码修改一个新密码从而登录,这可以使用smbpasswd或是Impacket中的smbpasswd.py工具来实现。
可以通过NetLocalGroup***类API来枚举用户组、用户组中的用户以及用户相关的属性等,在实际环境中红队人员可以使用rpcclient工具来枚举域、域用户、权限、枚举SID等等。
枚举域:
枚举组:
枚举用户:
值得一提的是由于操作最终都是由RPC函数实现,相比经常使用的net time /domain
、net group “Domain Administrators” /domain
这些命令,是不容易被检测的,其次如果红队人员在目标内网并不存在一个”Windows落脚点“也是适用的。
MS-TSCH协议用于注册和配置任务以及查询远程计算机上正在运行的任务的状态,而ITaskSchedulerService接口实现了使用XML任务定义的方式来控制计划任务的方法,方法示例如下图所示:
使用其中的SchRpcRegisterTask可以轻松地添加一个计划任务,MSDN定义如图:
通过MSDN提供的IDL可以直接编译调用进行计划任务的添加,直接利用XML来添加计划任务,XML格式在文档也有说明,关键代码如下:
配置计划任务的xml:
绑定到RPC后进行注册计划任务:
我们可以实现添加本机或是远程计划任务,来实现权限维持或是横向移动,通过RPC直接调用计划任务的方式可以绕过不少AV/EDR的防护进行安全测试,对于横向移动除了通过注册表回显,还有@zcgonvh提出的通过计划任务的Description回显。
类似于计划任务,从红队人员的视角来看,Windows服务也是一个常用的权限维持手段,除了权限维持,通常我们还会使用服务来加载驱动程序。
以使用SCManager来加载驱动程序为例,通常为使用Advapi32.dll中导出的OpenSCManager、CreateService来操作:
MS-SCMR,该协议用于远程管理服务控制管理器 (SCM),它是一种 RPC 服务器,可以实现服务配置和服务程序的控制;同样使用MS-SCMR中的IDL编译后,调用ROpenSCManagerA、RCreateServiceA也可以创建服务,函数结构分别如下图所示:
ROpenSCManagerA:
RCreateServiceA:
关键代码如下:
同样在添加服务上有着良好的规避性,同样的使用RPC去操作注册表等,是否也会有不同的效果?
seclogon,叫做辅助登录服务,该服务是一个RPC服务。
而MalSecLogon是@antonioCoco提出的,使用seclogon中的一些技巧来实现dump lsass的其中一项技术。其是为了不直接与lsass.exe进程交互而获取泄露的lsass句柄的一种方式。
我们创建进程的时候可以调用很多API,但其实最终都是由CreateProcess类API进行最终的创建调用,当使用advapi32.dll中导出的CreateProcessWithTokenW或者CreateProcessWithLogonW创建进程的时候,其实最终会用到seclogon服务中的SeclCreateProcessWithLogonW函数,接着实现创建进程的功能实现是由SlrCreateProcessWithLogon函数实现。
流程如下:
使用IDA或查看XP泄露源代码,可知advapi32.dll中的c_SeclCreateProcessWithLogonW函数封装了一个RPC调用,第一个参数是一个SECL_SLI结构:
因为创建进程必须要知道是谁调用的,以此来作为被创建进程的父进程。此结构中的ulProcessId是由GetCurrentProcessId()函数获取,GetCurrentProcessId()是获取当前进程TEB中的对应结构。
接着回到seclogon.dll中,最终SlrCreateProcessWithLogon得到被调用进程ID后,打开对应进程句柄:
更新进程的属性:
这样的话就出现了没有验证PID的缺陷,使我们可以更改当前进程TEB中的进程ID实现PPID Spoofing,这在绕过防护软件的进程链检测以及lsass dump等方面有良好的规避性。
这里值得一提的是,使用MalSecLogon这种方式创建进程并不需要seclogon服务开启,因为在进行RPC调用后,如果失败将会启动seclogon服务。
StartSeclogonService函数实现:
而且服务也有类似于其他Windows对象一样的ACL,根据seclogon服务的SDDL设定,通过交互式登录的用户(也就是AUTHORITY\INTERACTIVE)均有权限启动此服务。
最后,在一些提权Exploit里面的一个Trick也会用到seclogon服务,就是使用LogonUser这个API来添加一个有 NT AUTHORITY\INTERACTIVE SID 的令牌,代码可以参考文后链接 。
从最早的Printbug到现在比较有名的PetitPotam,都在攻防对抗、安全测试中频频出现。
PrintBug是利用RpcRemoteFindFirstPrinterChangeNotificationEx这个API来实现强制身份认证的
由于第四个参数可以是UNC路径,就导致了可以以SYSTEM账户权限去访问这个地址,其他的强制身份认证也都大同小异。
目前这类强制身份认证Bug主要有以下几种用途,并且是未修复的。
也称为ESC8攻击,在Windows AD域中,开启了ADCS服务,同时开启Web证书注册的话,就可以将NTLM认证请求relay到这个HTTP Endpoint;优点是通过 HTTP 协议relay,并不支持签名。
通过强制身份认证,中继DC或是其他机器账户请求至ADCS HTTP Endpoint,即可获得对应账户的证书,通过证书可以正常的申请TGT票据进行进一步访问。
这属于一种横向移动,横向扩展权限的方式,来获取正在运行webclient服务的机器权限;优点是强制通过HTTP进行身份验证,不存在签名的限制,结合基于资源的约束性委派,将机器账户发出的NTLM请求relay到LDAP,即可配置控制的机器账户到运行webclient服务的机器的资源的约束性委派。
这种攻击技巧也可以用来域内机器本地提权。
如果在PrintBug中指定UNC路径为\\localhost
,那么SYSTEM账户实际访问的路径为\\localhost\pipe\spoolss
;如果指定UNC路径为\\localhost/pipe/xxx
,SYSTEM账户实际访问的路径为\\localhost\pipe\xxx\pipe\spoolss
,而这个管道我们可以提前注册好,然后让SYSTEM账户访问这个管道,然后模拟RPC客户端安全上下文,利用token创建进程即可实现提权操作,当然需要SecurityImpersonation权限,所以只适用于服务账户。
比如pipepotato、PetitPotam都是以这种方式作为SERVICE to SYSTEM的提权手段。
MS-EVEN,该协议公开用于读取远程计算机上实时和备份事件日志中的事件的 RPC 方法;其中的ElfrOpenBELW,功能为打开一个事件日志句柄:
其中的第二个参数,BackupFileName,是指向备份事件日志所在文件的NT Object Path的一个Unicode字符串。
查看NT Object Path的介绍:
了解到NT Object Path这个字符串,也就是ElfrOpenBELW的第二个参数BackupFileName,必须以\??\
开头,根据示例,只需要构造\??\UNC\wmiscratch\scratch\x.x
字符串,服务器就会将其解释为\\wmiscratch\scratch\x.x.
使用MS-EVEN的IDL编译后进行调用,关键代码如下:
可以强制触发远程机器的身份认证,这样就得到了一个新的,同Printbug、PetitPotam类似的强制身份认证方式;遗憾的是该RPC服务所在的进程权限为NT AUTHORITY\LOCAL SERVICE,并不是高权限所以并不能用作命名管道模拟高权限用户来提权,只能用作强制身份认证,因为在域中SERVICE账户发起NTLM认证请求会以机器账户的身份发起。