The Windows Filtering Platform (WFP) is an important Windows system component that I had only ever endeavoured to understand in sufficient depth to meet current needs.
The Microsoft documentation says: “Windows Filtering Platform (WFP) performs its tasks by
integrating the following basic entities: Layers, Filters, Shims,
and Callouts.”
Use (and management) of rules in Windows Defender Firewall required
an understanding of WFP filters; interpreting the data captured by Microsoft
Message Analyser benefitted from understanding WFP layers and callouts;
experimenting with IPsec, VPN and DirectAccess benefitted from understanding
WFP layers, callouts and provider contexts.
One aspect of WFP that I dismissed/ignored as just a
grouping mechanism was WFP sublayers;
their role in classification and filter arbitration is described in the Microsoft documentation, but I never previously read this closely enough.
I wrote about Network Discovery last year and was surprised and embarrassed when I
noticed that the list of discovered computers under Windows 11 was incomplete
for reasons that I could not explain – the local computer (which had previously
always been in the list) was not present. Initially, I just quickly dismissed
this as a “by design” decision until I noticed a correlation between the
process of network discovery and WFP packet drop events. Here is the output of
the “netsh wfp show netevents” command for the drop event:
<header>
<timeStamp>2022-04-09T09:14:32.144Z</timeStamp>
<flags
numItems="9">
<item>FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET</item>
<item>FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET</item>
<item>FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET</item>
<item>FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET</item>
<item>FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET</item>
<item>FWPM_NET_EVENT_FLAG_APP_ID_SET</item>
<item>FWPM_NET_EVENT_FLAG_USER_ID_SET</item>
<item>FWPM_NET_EVENT_FLAG_IP_VERSION_SET</item>
<item>FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET</item>
</flags>
<ipVersion>FWP_IP_VERSION_V6</ipVersion>
<ipProtocol>17</ipProtocol>
<localAddrV6.byteArray16>::1</localAddrV6.byteArray16>
<remoteAddrV6.byteArray16>::1</remoteAddrV6.byteArray16>
<localPort>50602</localPort>
<remotePort>3702</remotePort>
<scopeId>0</scopeId>
<appId>
<data>5c006400650076006900630065005c0068006100720064006400690073006b0076006f006c0075006d00650033005c00770069006e0064006f00770073005c00730079007300740065006d00330032005c0073007600630068006f00730074002e006500780065000000</data>
<asString>\.d.e.v.i.c.e.\.h.a.r.d.d.i.s.k.v.o.l.u.m.e.3.\.w.i.n.d.o.w.s.\.s.y.s.t.e.m.3.2.\.s.v.c.h.o.s.t...e.x.e...</asString>
</appId>
<userId>S-1-5-19</userId>
<addressFamily>FWP_AF_INET6</addressFamily>
<packageSid>S-1-0-0</packageSid>
<enterpriseId/>
<policyFlags>0</policyFlags>
<effectiveName/>
</header>
<type>FWPM_NET_EVENT_TYPE_PUBLIC_CLASSIFY_DROP</type>
<classifyDrop>
<filterId>69067</filterId>
<layerId>46</layerId>
<reauthReason>0</reauthReason>
<originalProfile>0</originalProfile>
<currentProfile>0</currentProfile>
<msFwpDirection>MS_FWP_DIRECTION_OUT</msFwpDirection>
<isLoopback>true</isLoopback>
<vSwitchId/>
<vSwitchSourcePort>0</vSwitchSourcePort>
<vSwitchDestinationPort>0</vSwitchDestinationPort>
</classifyDrop>
<internalFields>
<internalFlags
numItems="1">
<item>FWPM_NET_EVENT_INTERNAL_FLAG_FILTER_ORIGIN_SET</item>
</internalFlags>
<capabilities/>
<fqbnVersion>0</fqbnVersion>
<fqbnName/>
<terminatingFiltersInfo
numItems="4">
<item>
<filterId>67000</filterId>
<subLayer>FWPP_SUBLAYER_INTERNAL_FIREWALL_APP_ISOLATION</subLayer>
<actionType>FWP_ACTION_PERMIT</actionType>
</item>
<item>
<filterId>66827</filterId>
<subLayer>FWPP_SUBLAYER_INTERNAL_FIREWALL_QUARANTINE</subLayer>
<actionType>FWP_ACTION_PERMIT</actionType>
</item>
<item>
<filterId>69067</filterId>
<subLayer>FWPP_SUBLAYER_INTERNAL_FIREWALL_WSH</subLayer>
<actionType>FWP_ACTION_BLOCK</actionType>
</item>
<item>
<filterId>66219</filterId>
<subLayer>FWPP_SUBLAYER_INTERNAL_FIREWALL_WF</subLayer>
<actionType>FWP_ACTION_PERMIT</actionType>
</item>
</terminatingFiltersInfo>
<filterOrigin>WSH
Default</filterOrigin>
<interfaceLuid>6755399457832960</interfaceLuid>
</internalFields>
The section highlighted in yellow was new to me and
particularly intriguing was the “terminatingFiltersInfo” data. It only became
clear later that what this showed was all of the sublayers in layer 46 (FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6)
that contained one or more filters that matched the packet. Within each
sublayer the filters are evaluated and the filter that delivers the “terminating”
action (based on filter weight, action, rights, etc. as discussed in the Filter Arbitration documentation) for that sublayer is reported.
Comparing the filters of Windows 10 and 11 systems gave part
of the answer why the local computer was missing from the list of computers.
The equivalent for the terminating filter for the FWPP_SUBLAYER_INTERNAL_FIREWALL_APP_ISOLATION
sublayer in Windows 11 (named “AppContainerLoopback”) is defined in the FWPM_SUBLAYER_MPSSVC_WSH
sublayer under Windows 10. The (blocking) terminating filter in the FWPP_SUBLAYER_INTERNAL_FIREWALL_WSH
sublayer is named “WSH Default Inbound Block”.
This means that in Windows 10, the “AppContainerLoopback” filter
can (and does, via weighting) override the “WSH Default Inbound Block” filter
because they are in the same sublayer; this is not true for Windows 11.
This change of sublayer for the “AppContainerLoopback”
loopback filter explains the difference in behaviour between Windows 10 and 11
but still leaves a mystery: there are 7 WSH rules/filters for the “Function
Discovery Provider Host” (fdphost) service and one, named “Allow inbound UDP
traffic to fdphost port 3702”, is possibly intended to allow responses to the WS-Discovery
multicast probes to be received.
Some more detailed tracing is needed to form a hypothesis
for this behaviour. The trace command that I used was:
pktmon start --trace --provider Microsoft-Windows-WFP --provider Microsoft-Windows-TCPIP --keywords 0x300408080 --level 17 --provider "TCPIP Service Trace" --keywords 0x17100 --level 6 --file-name why.etl
Provider Microsoft-Windows-WFP is an obvious choice and the Microsoft-Windows-TCPIP
provider with the keywords ut:TcpipDiagnosis, ut:AleRemoteEndpoint, ut:Loopback, ut:SendPath, ut:ReceivePath
limits the (verbose) output of that provider to the more relevant events. These
two providers give background information about what is happening at any
particular time and the "TCPIP Service Trace" with keywords WFP_TRACE_BASE, WFP_TRACE_FE, WFP_TRACE_STM, WFP_TRACE_ALE, NETIO_TRACE_TUNNEL
provides the details.
"TCPIP Service Trace" is a WPP (Windows Software
Trace Preprocessor) provider, so its data is difficult to interpret without the
corresponding private .pdb file. Here is an indication of the type of
information in the trace data:
This shows the packet being sent, no existing flow found and
each of the filters in the layer being tested against the packet:
The data made available to the filters is also logged, as is the final result:
Once the packet has passed the outbound filters, one can see that the packet is looped back and inbound filtering is started:
Finally, one can see that the packet is dropped:
The filter responsible for the drop (“WSH Default Inbound Block”) only has one filter condition and that is a match against FWPM_CONDITION_ALE_USER_ID. The information used for this condition is a self-relative TOKEN_ACCESS_INFORMATION structure and this is included in the trace (as a binary blob).
Formatting that blob shows something like this:
SidHash
Offset 0x58
SidHash 0x00000000 S-1-5-19
SidHash 0x00000060 S-1-16-16384
SidHash 0x00000007 S-1-1-0
SidHash 0x00000007 S-1-5-32-545
SidHash 0x00000007 S-1-5-6
SidHash 0x00000007 S-1-2-1
SidHash 0x00000007 S-1-5-11
SidHash 0x00000007 S-1-5-15
SidHash 0x0000000E
S-1-5-80-364023826-931424190-487969545-1024119571-74567675
SidHash 0xC000000F S-1-5-5-0-11718649
SidHash 0x00000007 S-1-2-0
SidHash 0x00000007
S-1-5-32-3167453650-624722384-889205278-321484983-714554697-3592933102-807660695-1632717421
SidHash 0x00000007
S-1-5-32-383293015-3350740429-1839969850-1819881064-1569454686-4198502490-78857879-1413643331
SidHash 0x00000007
S-1-5-32-2035927579-283314533-3422103930-3587774809-765962649-3034203285-3544878962-607181067
SidHash 0x00000007
S-1-5-32-3659434007-2290108278-1125199667-3679670526-1293081662-2164323352-1777701501-2595986263
SidHash 0x00000007
S-1-5-32-11742800-2107441976-3443185924-4134956905-3840447964-3749968454-3843513199-670971053
SidHash 0x00000007
S-1-5-32-3523901360-1745872541-794127107-675934034-1867954868-1951917511-1111796624-2052600462
SidHash 0x00000007 S-1-5-32-1488445330-856673777-1515413738-1380768593-2977925950-2228326386-886087428-2802422674
RestrictedSidHash Offset 0x4A0
Privileges Offset 0x800
Privilege 0x00000003 0x0000000000000017
Privilege 0x00000003 0x000000000000001D
AuthenticationId 0x3E5
TokenType TokenPrimary
ImpersonationLevel SecurityAnonymous
MandatoryPolicy NO_WRITE_UP, NEW_PROCESS_MIN
Flags 0x1002800
AppContainerNumber 0
CapabilitiesHash Offset 0x5B0
SecurityAttributes Offset 0x6C0
SecurityAttributes Name="TSA://ProcUnique" Type=2 Flags=0x0 Count=2
X1=0x41
Value[0]=245
Value[1]=11718747
The
S-1-5-80 (service SID) is the service SID of the receiving process (“fdphost” (Function
Discovery Provider Host)).
fdphost sends a WS-Discovery probe to a multicast address
and UDP port 3702, but it sends the probe from its randomly assigned local port
number; replies to the probes are sent back to this port number. Non-loopback
replies are permitted by an ALE multicast flow but, for currently
unknown reasons, loopback replies are subjected to a full “classification” –
which results in a drop decision. My hypothesis is that no attempt is made to match loopback packets against existing ALE multicast flows.
I searched the web for mentions of the local system not appearing in the list of discovered computers and found none. I also asked on the Microsoft Q&A website and received one report that the issue did not appear to be present – so the hypothesis is unconfirmed (or even “in doubt”) at the moment…
No comments:
Post a Comment