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.
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.
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.
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.
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.
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.
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:
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)
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:
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.
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:
In order to archieve this, we will be using the actions “allow” and “deny” as well as the audit setting “true”.
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
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
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
The following YouTube tutorial provided by the developers of the RPC firewall provides some insights in how to install the software:
https://github.com/zeronetworks/rpcfirewall
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.