2. rpc介绍(是什么、有什么用、谁在用)
2.1 RPC介绍
RPC协议主要用来进行远程过程调用,用一句话来概括,就是允许用户程序调用服务器上的函数进行计算,由此实现两者交互。
早先的企业环境中,所有的服务都在一台主机上,就会导致服务器负荷过重,无法保证业务的正常运作。正因如此,后来企业就更换了一种思路,将不同服务分开,分别存放在不同主机上,暂时解决了负荷问题。但是久而久之,这样的方式也开始显现弊端,比如当用户需要使用不同服务器上的服务协作来完成任务时,服务与服务之间该如何交互?
这就是RPC要解决的问题,简言之,RPC可以允许一台机器上的程序调用另一台机器上的函数,通过各计算机协作进行计算,以保证用户任务顺利完成,RPC的通信过程如下图所示(摘自微软官方)
客户端和服务器在各自的本地维护一个stub(理解为函数工厂),stub里面会暴露出客户端可以调用(服务器可以解析)的函数,客户端stub在收到这些函数之后会将其序列化并通过网络传递给服务器;服务器stub在收到函数调用之后会将序列化的内容解序列化,并调用本地对应的函数,获得结果之后序列化结果并传递给客户端。客户端会按照相同的方式反序列化结果。
2.3 有什么用
- 分布式 如上所说,我们可以利用RPC的这个通信方式将服务分散到不同的服务器上部署,在应用层面调用远程服务就像在本地调用一样简单。在很多大型架构上可以看到它的身影如Dubbo,当然这不是本次讨论的重点。
- 本地跨进程通信 RPC也可以在本地进行调用,将RPC客户端和服务端放在同一服务器,实现不同进程之间的通信。
2.4 谁在用
在Windows上面,很多功能都利用到了RPC通信,身份验证、服务创建、目录复制等。最典型的就是lsass.exe进程,我们用RpcView可以看到很多程序都有提供Rpc接口,下面是lsass.exe的rpc接口
- 服务创建 (MS-SCMR)
- 目录复制服务 (MS-DRSR)
- 远程注册表 (MS-RRP)
- 计划任务 (MS-SCMR)
- 打印系统 (MS-RPRN)
- Windows 管理规范 (MS-WMI)
- Netlogon 远程协议 (MS-NRPC)
其他的,很多大型架构上可以看到它的身影如Dubbo,当然这不是本次讨论的重点。
3. 攻击面
针对Windows上的Rpc攻击面,目前在互联网上看到大多数都是在寻找Rpc接口中可以滥用的函数,典型案例就是Printer Bug和PetitPotam。
Printer Bug 利用的是\pipe\spoolss
接口中的 RpcRemoteFindFirstPrinterChangeNotificationEx() 函数,该函数会创建一个远程更改通知对象,该对象监视打印机对象的更改,如果指向的打印机路径为远程打印机,则RPC服务器会像远程打印机发起认证。
PetitPotam 利用的是\pipe\efsrpc
接口中的 EfsRpcOpenFileRaw() 函数,该函数用于打开服务器上的加密对象以进行备份或还原,当指定的加密对象为UNC路径时,RPC服务器就会去查找该UNC路径,同时会发起认证请求。
漏洞 | Protocol | function |
---|---|---|
Printer Bug | MS-RPRN | RpcRemoteFindFirstPrinterChangeNotificationEx() |
PetitPotam | MS-EFSR | EfsRpcOpenFileRaw() |
4. rpc挖掘方法
寻找可滥用的Rpc接口
- RpcView手动分析每一个接口
- Ghidra + Jupyter 图形化分析(该方法时用脚本导出所有具有Rpc功能的DLL,再用Ghidra将DLL进一步处理,输出出每个DLL具有的Rpc函数,最后将结果导入到Jupyter进行分析)
5. Printer BUG
Printer BUG 这个洞利用的是spoolsv.exe
,它里面有一个Rpc 端点\pipe\spoolss
,RPC 服务里面存在一个函数 RpcRemoteFindFirstPrinterChangeNotificationEx
。
可以在MSDN中找到相关函数的说明:
RpcRemoteFindFirstPrinterChangeNotificationEx 创建一个远程更改通知对象,该对象监视打印机对象的更改,并使用RpcRouterReplyPrinter(第 3.2.4.1.2 节) 或RpcRouterReplyPrinterEx(第 3.2.4.1.4 节)将更改通知发送到打印客户端。
继续查看文档,发现第四个参数接收一个打印服务器的路径,在官方文档中同样给出说明,该路径必须是DNS, NetBIOS, IPv4, or Universal Naming Convention (UNC) name。
UNC路径?那是不是说可以指向一个攻击者的UNC路径呢?
流程为:
SMB -> 认证 testuser@password
SMB -> 绑定Rpc管道,UUID:12345678-1234-ABCD-EF00-0123456789AB,拿到句柄
SMB -> RpcRemoteFindFirstPrinterChangeNotificationEx()
,设置访问UNC路径为攻击者的UNC路径。
SMB -> 服务器此时响应请求,像攻击着发起TCP连接,服务器通过SMB像攻击者发起NTLMSSP认证,服务器认证的用户为TEST\DC$
攻击结束
6. PetitPotam
在lsass.exe
进程中有一个接口c681d488-d850-11d0-8c52-00c04fd90f7e
,它有一些EFS文件相关操作的函数,查看MSDN相关文档可以发现,该接口中客户端与服务端之间的通信依赖\pipe\lsarpc
和\pipe\efsrpc
两个命名管道。
继续查看EFS相关函数,EfsRpcOpenFileRaw()
函数用于打开服务器上的加密对象进行备份或还原。参数FileName
指定加密对象的UNC路径,那么同样的,我们可以指定一个攻击者服务器上的UNC路径。

SMB -> 匿名认证,绑定IPC$
,在匿名共享中创建lsarpc
文件
DCERPC -> 绑定RPC接口\pipe\lsarpc
,c681d488-d850-11d0-8c52-00c04fd90f7e
EFS -> 发起EfsRpcOpenFileRaw()
请求,设置fileName
=\\attack\xxx
SMB -> 服务器响应操作,连接指定UNC路径,同时进行NTLM_SSP
身份验证
EFS -> 将操作结果返回给Rpc客户端
SMB -> 断开连接