RPC or Not, Here We Log: Preventing Exploitation and Abuse with RPC Firewall
Welcome, readers, to the first installment of our blog series βPreventing Exploitation and Abuse with the RPC Firewallβ.
In this post, weβll delve into how to create rules for the RPC firewall and how to deploy them onto our servers.
In the year 2024, weβll release the second part of this series, where weβll explore detection possibilities by analyzing the generated Windows events to further enhance your security posture.
Introduction
Remote Procedure Call (RPC) plays an important role in Windows environments today. RPC is a fundamental mechanism that enables communication between processes, allowing them to request services from one another across a network. In Windows, RPC is utilized extensively for various system functions, such as file and printer sharing, Active Directory authentication, and remote management. However, the widespread use of RPC also makes it an attractive target for attackers.
Why should we care?
By exploiting vulnerabilities in RPC implementations, malicious actors can gain unauthorized access, execute arbitrary code, and compromise the security and integrity of a Windows environment. Thus, it is of paramount importance to implement robust security measures to protect against RPC-based attacks, ensuring the confidentiality, availability, and integrity of critical systems and data.
Shoutout to the Zero Networks research team, who built a tool called βRPC Firewallβ, a free and open source tool that allows the prevention and auditing of RPC calls.
What can the RPC Firewall do for me?
Remote RPC Attacks β Detection
When the RPC firewall configuration is configured to audit, RPC events are written to the Windows Event Log and allow for a forward to a central detection and analysis platform.
The created event entries can then be forwarded to the SIEM and used to create baselines of remote RPC traffic for various servers in the environment.
Once an abnormal RPC call is audited it can be used to trigger an alert for your SOC/CSIRT team for analysis.
RPC Firewall log entries can be found inside the Windows Event Viewer path βApplication/RPCFWβ.
RPC Filter events can be found inside the Windows Security log with the event ID 5712.
Remote RPC Attacks β Prevention
Besides logging, the RPC Firewall can be configured to block potentially malicious RPC calls.
All other RPC calls are not audited to reduce noise, save storage space and keep the performance impact minimal.
Once a potentially malicious RPC call is detected, it is blocked and audited/logged which can then be used to alert your SOC/CSIRT team, while keeping the servers protected.
Components of the RPC Firewall
The RPC Firewall has 3 main components:
The rpcFwManager.exe is the main executable that is being used by the RPC Firewall service in the deployment but is also used to reload the changed configuration.
The file rpcFireWall.dll is injected into the processes in order to allow auditing and filtering of the RPC calls.
The file rpcMessages.dll is a common library file used for logic that is shared between the other components and responsible for creating and writing the events to the Windows Event log.
The file RpcFw.conf is the configuration file containing our defined ruleset that will be used to protect and log legitimate use of RPC endpoints.
Create an RPC Filter/Firewall rule
Although the provided rules have been tested in our lab environment, we highly recommend to test the firewall rules in a test or pre-production environment before deploying them into a production network!
In order to create an RPC firewall rule (Firewall or Filter) we have to complete the following steps:
- Identify the UUID of the RPC call we want to allow/block/audit
- Identify the operation number (Opnum) of the method
- Collect possible whitelisted IPs of endpoints that should be allowed to access the RPC methods
- Decide if we want to block/allow and/or audit the call
Identify UUID and Operation number of an RPC call
For this example we are going to look at how the script βsecretsdump.pyβ from the impacket toolkit executes the DCSync attack in order to create a rule that prevents it.
If we take a look at the script here:
https://github.com/fortra/impacket/blob/master/impacket/examples/secretsdump.py#L571
We can identify the method used by analyzing the following lines:
[...] def _DRSGetNCChanges(self, userEntry, dsName): if self.__drsr is None: self.__connectDrds() LOG.debug('Calling DRSGetNCChanges for %s ' % userEntry) request = drsuapi.DRSGetNCChanges() [...]
Which means that impacket is using the RPC method βIDL_DRSGetNCChangesβ, which is documented by Microsoft here:
According to the Microsoft Documentation, βthe IDL_DRSGetNCChanges method replicates updates from an NC replica on the serverβ.
As the following sidebar shows, it is part of the RPC interface called βdrsuapiβ.
In order to create a rule we do need the UUID for the affected interface and we can find that information here:
Parameter | Value | Reference |
RPC interface UUID for drsuapi methods | e3514235-4b06-11d1-ab04-00c04fc2dcd2 | Section 4.1.1 β section 4.1.29 |
β¦ | β¦ | β¦ |
This gives us the needed UUID for the RPC interface.
You might have noticed the operation number in the screenshot above and that is indeed what we are looking for and thus we do already have the operation number β3β for our rule.
DRSGetNCChanges -> 4.1.10 IDL_DRSGetNCChanges (Opnum 3)
Identifying allowed endpoints
We are now missing the IP addresses for which the DCSync actions should be allowed and/or audited.
In a general environment, DCSync is a part of the Active Directory replication process, and it allows a domain controller to request and pull the latest information about user accounts, security groups, and other objects from another domain controller. This synchronization is crucial for maintaining consistency and ensuring that all domain controllers have up-to-date information.
This also means that we do not want our RPC firewall to block legitimate RPC calls and thus prevent the DCSync and cause problems in our production environment.
For this example, letβs go with the following environment where we do have 2 domain controllers:
- DC1.ecorp.local (IP: 10.0.31.5)
- DC2.ecorp.local (IP: 10.0.31.6)
This post assumes that, as part of the network configuration, the domain controllers are assigned a static IP address. If your network depends on domain controllers retrieving their IP addresses from a pool, the rule will not automatically update and thus block the DCSync actions sooner or later.
Identifying possible actions
In order to correctly configure the rules, we need to define what our use case of the RPC firewall will be. In this example we want:
- Domain controllers to be able to synchronize with each other
- Blocking of all other access to DCSync operations on the RPC endpoint
- Logging of attempts to DCSync in order to detect malicious use or possible configuration problems
In order to archieve this, we will be using the actions βallowβ and βdenyβ as well as the audit setting βtrueβ.
Checking the current status of the Local Security Authority (LSA) Protection
Because the RPC Firewall protection interacts with the LSASS process on the server it is deployed on, we first have to identify if LSA Protection is enabled in order to decide if our rule set will be based on RPC filters or the RPC firewall rules.
The current status of the LSA Protection can be checked by using the registry or checking for a group policy that was created in order to set these values.
For more information please check the official Microsoft page: https://learn.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection#enable-lsa-protection-by-using-group-policy
Check by using the registry
- Open the Registry Editor RegEdit.exe, and navigate to the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa.
- Check the value of the registry key:
- βRunAsPPLβ=dword:00000000 = Disabled
- βRunAsPPLβ=dword:00000001 = Enabled with a UEFI variable
- βRunAsPPLβ=dword:00000002 = Enabled without a UEFI variable (only enforced on Windows 11 build 22H2 and higher)
Rule creation with LSA Protection enabled (RPC filters)
Because LSA Protection is enabled, the DLL cannot be injected into the LSASS process and thus the RPC firewall does not apply to operations happening inside the application space of the LSASS process. This means we can only rely on RPC filters.
Because of this restriction we will be working only with RPC filters. Which limitations this might have can be accessed here: https://github.com/zeronetworks/rpcfirewall#using-rpc-firewall-or-rpc-filters
For the RPC filters we will be making use of the additional parameters βprotβ and βsidβ in order to fine tune our rule set as the parameter βopnumβ is not available when using the RPC filters.
The parameter βprotβ specifies the protocol sequence the rule should match for.
In our example, we will be using βConnection-oriented named pipesβ and this means a value of βncacn_npβ for the parameter βprotβ.
Constant/value | Description |
---|---|
β¦ | β¦ |
ncacn_np Connection-oriented named pipes | Client only: MS-DOS, Windows 3.x, Windows 95 Client and Server: Windows Server 2003, Windows XP, Windows 2000, Windows NT |
β¦ | β¦ |
The parameter βsidβ is one of the Microsoft built-in security identifiers, which can be be found in an overview under the following URL: https://learn.microsoft.com/en-us/windows/win32/secauthz/sid-strings
In our example we will be using:
SDDL SID string | Constant in Sddl.h | Account alias and corresponding RID |
---|---|---|
βBAβ | SDDL_BUILTIN_ADMINISTRATORS | Built-in administrators. The corresponding RID is DOMAIN_ALIAS_RID_ADMINS. |
β¦ | β¦ | β¦ |
βSYβ | SDDL_LOCAL_SYSTEM | Local system. The corresponding RID is SECURITY_LOCAL_SYSTEM_RID. |
β¦ | β¦ | β¦ |
As βBAβ should not be allowed in order to prevent local administrators from using DCSync on the target and βSYβ should be allowed in order to allow the local system or machine account to call the RPC endpoint successfully.
By using the information prepared in the previous steps and our requirements the DCSync can be allowed from both the domain controllers using the following rules:
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 prot:ncacn_np sid:BA addr:10.0.31.5 action:allow audit:true
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 prot:ncacn_np sid:BA addr:10.0.31.6 action:allow audit:true
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 sid:SY action:allow audit:true
Because we want to block local administrators from being able to DCSync even with the correct permissions and log any tries to do so, we add the following rule:
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 sid:BA action:block audit:true
As we cannot make use of the operation number and just block one specific operation, we decided to allow but audit all further requests to the RPC endpoint. This can be reflected in the following rule:
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 action:allow audit:true
This results in the following final RPC filter rule set for the file βRpcFw.confβ:
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 prot:ncacn_np sid:BA addr:10.0.31.5 action:allow audit:true
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 prot:ncacn_np sid:BA addr:10.0.31.6 action:allow audit:true
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 sid:SY action:allow audit:true
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 sid:BA action:block audit:true
flt:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 action:allow audit:true
Rule creation with LSA Protection disabled (Firewall)
In order to allow the DCSync from domain controllers and audit the calls we will set the two following rules:
fw:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 addr:10.0.31.5 opnum:3 action:allow audit:true
fw:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 addr:10.0.31.6 opnum:3 action:allow audit:true
As our requirement was that we want to block all other access to DCSync operations on the RPC endpoint and we also wanted to log attempts to DCSync in order to detect malicious use or possible configuration problems, we will be adding this additional rule:
fw:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 opnum:3 action:block audit:true
This results in the final rule set for the configuration file βRpcFw.confβ being:
fw:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 addr:10.0.31.5 opnum:3 action:allow audit:true
fw:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 addr:10.0.31.6 opnum:3 action:allow audit:true
fw:uuid:e3514235-4b06-11d1-ab04-00c04fc2dcd2 opnum:3 action:block audit:true
Create the Configuration file βRpcFw.confβ in the same directory as the executable βRpcFwManager.exeβ and insert your rules in there.
Whenever the configuration changes, you need to notify the rpcFirewall.dll via the update command: RpcFwManager.exe /update
Deployment
The following YouTube tutorial provided by the developers of the RPC firewall provides some insights in how to install the software:
References
https://github.com/zeronetworks/rpcfirewall
Steffen Rogge
Steffen is a Cyber Security Consultant at NVISO, where he mostly conducts Purple & Red Team assessments with a special focus on TIBER engagements.
This enables companies to evaluate their existing defenses against emulated Advanced Persistent Threat (APT) campaigns.