深入解析Windows防火墙RPC过滤机制

本文详细解析了Windows防火墙RPC过滤层的工作原理,包括规则配置、用户模式层处理机制、RPC运行时加载流程以及安全回调中的过滤检查过程,为研究RPC安全防护提供技术参考。

Windows防火墙RPC过滤器工作原理

我曾承诺会发布一篇关于Windows RPC过滤器工作原理的博客文章。在发布了更通用的Windows防火墙文章后,我认为应该再写一篇关于RPC过滤器本身的短文。如果你不了解背景,Windows防火墙具有限制RPC接口访问的能力。由于对RPC相关技术的重新关注(特别是PetitPotam技巧),这一点显得尤为重要。例如,你可以使用以下通过netsh命令运行的脚本来阻止对EFSRPC接口的任何访问:

1
2
3
4
5
6
7
8
rpcfilter
add rule layer=um actiontype=block
add condition field=if_uuid matchtype=equal data=c681d488-d850-11d0-8c52-00c04fd90f7e
add filter
add rule layer=um actiontype=block
add condition field=if_uuid matchtype=equal data=df1941c5-fe89-4e79-bf10-463657acf44d
add filter
quit

这个脚本添加了两条规则,将阻止对UUID为c681d488-d850-11d0-8c52-00c04fd90f7edf1941c5-fe89-4e79-bf10-463657acf44d的RPC接口的任何调用。这些对应两个EFSRPC接口。

防火墙上下文中的工作原理

Windows过滤平台的内核组件是否有内置的RPC协议解析器来阻止连接?这太复杂了,实际上所有操作都是在用户模式下通过一些特殊层完成的。如果使用NtObjectManager的防火墙Get-FwLayer命令,可以通过过滤IsUser属性来检查注册在用户模式下运行的层。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
PS> Get-FwLayer | Where-Object IsUser

KeyName                       Name
-------                       ----
FWPM_LAYER_RPC_PROXY_CONN     RPC Proxy Connect Layer
FWPM_LAYER_IPSEC_KM_DEMUX_V4  IPsec KM Demux v4 Layer
FWPM_LAYER_RPC_EP_ADD         RPC EP ADD Layer
FWPM_LAYER_KM_AUTHORIZATION   Keying Module Authorization Layer
FWPM_LAYER_IKEEXT_V4          IKE v4 Layer
FWPM_LAYER_IPSEC_V6           IPsec v6 Layer
FWPM_LAYER_IPSEC_V4           IPsec v4 Layer
FWPM_LAYER_IKEEXT_V6          IKE v6 Layer
FWPM_LAYER_RPC_UM             RPC UM Layer
FWPM_LAYER_RPC_PROXY_IF       RPC Proxy Interface Layer
FWPM_LAYER_RPC_EPMAP          RPC EPMAP Layer
FWPM_LAYER_IPSEC_KM_DEMUX_V6  IPsec KM Demux v6 Layer

在输出中,我们可以看到5个名称中包含RPC的层:

  • FWPM_LAYER_RPC_EP_ADD - 过滤进程创建的新端点
  • FWPM_LAYER_RPC_EPMAP - 过滤对端点映射器信息的访问
  • FWPM_LAYER_RPC_PROXY_CONN - 过滤到RPC代理的连接
  • FWPM_LAYER_RPC_PROXY_IF - 过滤通过RPC代理的接口调用
  • FWPM_LAYER_RPC_UM - 过滤到RPC服务器的接口调用

RPC UM层的工作机制

我们将重点讨论FWPM_LAYER_RPC_UM层的工作原理,因为这是脚本开始时使用的层。添加RPC过滤规则后,运行以下命令可以查看新创建的规则:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PS> Get-FwFilter -LayerKey FWPM_LAYER_RPC_UM -Sorted | Format-FwFilter

Name        : RPCFilter
Action Type : Block
Key         : d4354417-02fa-11ec-95da-00155d010a06
Id          : 78253
Description : RPC Filter
Layer       : FWPM_LAYER_RPC_UM
Sub Layer   : FWPM_SUBLAYER_UNIVERSAL
Flags       : Persistent
Weight      : 567453553048682496
Conditions  :
FieldKeyName               MatchType Value
------------               --------- -----
FWPM_CONDITION_RPC_IF_UUID Equal     df1941c5-fe89-4e79-bf10-463657acf44d

Name        : RPCFilter
Action Type : Block
Key         : d4354416-02fa-11ec-95da-00155d010a06
Id          : 78252
Description : RPC Filter
Layer       : FWPM_LAYER_RPC_UM
Sub Layer   : FWPM_SUBLAYER_UNIVERSAL
Flags       : Persistent
Weight      : 567453553048682496
Conditions  :
FieldKeyName               MatchType Value
------------               --------- -----
FWPM_CONDITION_RPC_IF_UUID Equal     c681d488-d850-11d0-8c52-00c04fd90f7e

FWPM_CONDITION_RPC_IF_UUID条件键用于指定要匹配的接口UUID。FWPM_LAYER_RPC_UM层有许多可过滤的字段,可以通过检查层对象的Fields属性来查询:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
PS> (Get-FwLayer -Key FWPM_LAYER_RPC_UM).Fields

KeyName                           Type      DataType
-------                           ----      --------
FWPM_CONDITION_REMOTE_USER_TOKEN  RawData   TokenInformation
FWPM_CONDITION_RPC_IF_UUID        RawData   ByteArray16
FWPM_CONDITION_RPC_IF_VERSION     RawData   UInt16
FWPM_CONDITION_RPC_IF_FLAG        RawData   UInt32
FWPM_CONDITION_DCOM_APP_ID        RawData   ByteArray16
FWPM_CONDITION_IMAGE_NAME         RawData   ByteBlob
FWPM_CONDITION_RPC_PROTOCOL       RawData   UInt8
FWPM_CONDITION_RPC_AUTH_TYPE      RawData   UInt8
FWPM_CONDITION_RPC_AUTH_LEVEL     RawData   UInt8
FWPM_CONDITION_SEC_ENCRYPT_ALGORITHM RawData UInt32
FWPM_CONDITION_SEC_KEY_SIZE       RawData   UInt32
FWPM_CONDITION_IP_LOCAL_ADDRESS_V4 IPAddress UInt32
FWPM_CONDITION_IP_LOCAL_ADDRESS_V6 IPAddress ByteArray16
FWPM_CONDITION_IP_LOCAL_PORT      RawData   UInt16
FWPM_CONDITION_PIPE               RawData   ByteBlob
FWPM_CONDITION_IP_REMOTE_ADDRESS_V4 IPAddress UInt32
FWPM_CONDITION_IP_REMOTE_ADDRESS_V6 IPAddress ByteArray16

过滤器的实现机制

由于RPC协议的复杂性,过滤是在RPC服务器进程中通过RpcRtRemote扩展DLL实现的。除了RPCSS之外,默认情况下不会加载此DLL。只有当WNF_RPCF_FWMAN_RUNNING WNF状态存在值时才会加载。以下显示了使用netsh添加两个RPC过滤规则后的状态:

1
2
3
4
5
PS> $wnf = Get-NtWnf -Name 'WNF_RPCF_FWMAN_RUNNING'
PS> $wnf.QueryStateData()
Data ChangeStamp
---- -----------
{}             2

RPC运行时设置了一个订阅,以便在WNF值发生更改时加载DLL。加载后,RPC运行时将注册所有当前接口以检查防火墙。在安全回调的正常处理过程中,当对接口进行调用时,会检查过滤规则。运行时将调用RpcRtRemote中的FwFilter函数,传递有关防火墙接口调用的所有详细信息。

过滤处理过程

过滤调用仅针对DCE/RPC协议进行,不包括ALPC。此外,仅当调用方是远程调用时才会调用。如果调用通过TCP进行,则始终如此;但对于命名管道,仅当管道通过SMB打开时才会调用。

FwFilter函数构建与FWPM_LAYER_RPC_UM层字段列表对应的防火墙值列表,并将它们与层的数字ID一起传递给FwpsClassifyUser0 API。此API将枚举该层的所有过滤器并应用条件检查,返回分类结果(例如阻止或允许)。基于此分类,RPC运行时可以允许或拒绝调用。

为了使过滤器可访问进行分类,RPC服务器必须对引擎具有FWPM_ACTRL_OPEN访问权限,并对过滤器具有FWPM_ACTRL_CLASSIFY访问权限。默认情况下,Everyone组具有这些访问权限,但AppContainers和其他可能的沙箱没有。然而,通常AppContainer进程不会创建特权RPC服务器,至少远程攻击者不会发现有用的服务器。可以使用Get-AccessibleFwObject命令检查各种防火墙对象的访问权限:

1
2
3
4
5
6
7
PS> $token = Get-NtToken -Filtered -Flags LuaToken
PS> Get-AccessibleFwObject -Token $token | Where-Object Name -eq RPCFilter

TokenId Access          Name
------- ------          ----
4ECF80  Classify|Open RPCFilter
4ECF80  Classify|Open RPCFilter
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计