Lateral Movement using DCOM Objects - How to do it the right way?
Lateral Movement using DCOM Objects - How to do it the right way?
Devious adjective. /ˈdiː.vi.əs/ Indirect in departing from the accepted or proper way; misleading.
Introduction
Lateral movement is a stage in which the attacker tries to deepen his foothold by moving to other devices in the network.
All this happens after gaining a foothold on one of the devices on the network, and assuming that the compromised machine in which it resides, does not contain or cannot access information/assets or a system that it has defined as an operational target.
The attacker will try to move laterally between different machines, devices, or assets in the network, in order to attack its targets, such as taking over sensitive environments a system containing relevant information, or any asset that has been defined as an operational target in the attack (Crown Jewels).
Here are some examples where an attacker would need to lateral his movement across the network:
After exploiting web app weakness that leads to command execution on the server, and the attacker wants to reach another asset on the network (e.g. The Database).
After taking over an organization employee's computer by sending a malicious file to the corporate email, when the attacker wants to take over other machines who belong to users with stronger access in the organization (e.g. Compromise a user's machine with Domain Admin Permissions).
After gaining access to the organization's network (Wi-Fi or cable), where the attacker's goal is to gain a foothold of a user associated with the organization's domain and privileges, in order to access the file server that contains financial information.
There are a large number of tactics for performing lateral movement concepts, most of which are documented in a database maintained by MITRE.
This article will be based on the technique of lateral movement using DCOM Objects (Mitre documentation):
In recent years, a number of methods have been developed for performing lateral movement using objects on via DCOM protocol, which is enabled by default in Windows series operating systems.
DCOM Objects also has considerable use of software built into the operating system (e.g. Internet Explorer) and external software (e.g. Microsoft Office).
Some of these programs export objects that publicize functions that allow you to run commands on the operating system.
This technique is considered efficient and quiet, due to the fact these objects come with operating system support by default, allowing the attacker to exploit them on almost any enterprise network based on Windows.
As mentioned, the use of DCOM Objects is considered "legitimate", since the operating system uses this protocol frequently.
It can be concluded that there is a high probability that the firewall and ACL settings in the organization will allow interaction with this protocol.
As part of personal research, that I did about DCOM Objects, I was interested to know how to locate and validate exported functions on a specific object that allows command execution through the operating system.
I spoke with my good friend, Refael Ivgi, who gave me interesting references and sources for conducting dynamic and static exploration of objects.
After understanding a bit how it works, I decided to take it to my world, and write down a script that would do the job for me.
The idea was to write a script that allows to locate, validate and utilize exported functions from a specific object, and validates whether our user is allowed to execute commands on the local machine, and then execute commands on remote machines on the entire network.
The development process began to become complex and the script became a real tool.
The tool is named DVS, from the word Devious and also an acronym for DCOM Weaknesses Scanner, and it contains all the concepts that exist in the article, and even a little beyond ☺.
You are welcome to observe the code which can be found here on GitHub.
As well as this YouTube showreel video illustrating lateral movement to other machines using the tool:
A few terms before we are getting started
COM Object (Short for Component Object Model):
Is a binary interface that externalizes a collection of functions using an object.
This object allows you to import functions that has been compiled once and use it in a number of different programs without requiring re-compiling in order to be supported by the same programs.
In addition, the COM model allows objects to communicate to each other, regardless of how they work or the language in which they are written.
Think of it as a DLL, which instead of being exported and implemented by importing a file (e.g. a DLL file), is exported and implemented on a server that receives and returns information (COM Server, we will expand below).
For example: creates a graphic COM object of "square button with round corners and green background" and use it in any window which should show the user "OK" and "Cancel" buttons, and wrap them with the same design features (square button, round corners and green background) .
A COM object allows you to import functionality / component from any software that exports such an object.
From a graphic object - to a complete program that is a COM object (e.g. Internet Explorer packaged and exported as an object).
You can read a broader explanation from the documentation of Microsoft.
Example of code snippet that executing a command using COM Object named Wscript.Shell:
Example of a code snippet that extracts the list of existing COM Objects in the local machine:
PS> Function Get-ComList {
$path = "REGISTRY::HKey_Classes_Root\clsid\*\progid"
foreach ($val in dir $path) {
$val.getvalue("")
}
}
PS> Get-ComList
Here is an example of an output that contains the list of objects in the Win10 machine with default settings:
OLE (Short for: Object Linking and Embedding):
Is a technology for linking objects and assimilating them using COM Objects.
This technology enables the implementation of an object that is exported by one process into another, Between different apps. For example: Viewing an Excel spreadsheet inside a Word document.
In addition, OLE is also the name of a data retention format that is also the format of Office binaries and other Windows components such as SHELL components like thumbs.db.
OLE is based on the COM infrastructure. Any COM object that implements the interface as an IOleObject is considered an OLE object.
Example of a code snippet that extracts the list of existing OLE Objects in the local machine:
Here is an example of an output that contains the list of objects in the Win10 machine with default settings:
ActiveX: is an OLE object that supports an IUnknown object.
In short, ActiveX is the first technology that allowed a website to execute a snippet of code in different languages within an HTML page that would interact with applications in the operating system or run a software component within the browser. This is an example of an HTML page with code snippets in different languages that run an ActiveX object that opens the CDROM:
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=5">
</head>
<body>
<!-- VBScript Example: -->
<script language="VBScript">
<!--
' Access the Windows Media Player CD-ROM collection
Set oWMP = CreateObject("WMPlayer.OCX.7")
Set colCDROMs = oWMP.cdromCollection
' If the computer has at least one CD-ROM drive...
If colCDROMs.Count >= 1 Then
' ...eject each one
For i = 0 To colCDROMs.Count - 1
colCDROMs.Item(i).Eject
Next ' As in "next CD-ROM drive"
End If
-->
</script>
<!-- And in JScript, Microsofts version of JavaScript: -->
<script language="JavaScript">
<!--
// Access the Windows Media Player CD-ROM collection
var oWMP = new ActiveXObject("WMPlayer.OCX.7");
var colCDROMS = oWMP.cdromCollection;
// If the computer has at least one CD-ROM drive, eject each one
if (colCDROMS.count >= 1) for (i = 0; i > colCDROMS.count; i++) colCDROMS.item(i).eject();
-->
</script>
</body>
</html>
COM+ Object:
is an expansion of COM Object, which implements a better security and performance model. This extension allows applications and components to communicate over the network. For example: Software that can load a COM+ component of Software B without fear of compromising its security.
Security is created because COM components that are registered as + COM will load in "Out of Process" mode and will actually be hosted by an external application. Sample Scenario: The MyApp.exe application loads the COM+ component named "Pdump.ProcessDump" (I recommend you to research about it), the COM+ component will load within an intermediary process such as dllhost.exe or another operating system process.
Here is a code that extracts the list of existing COM+ Components on the local machine:
And in the procedure, an example of the output that contains the list of objects in the Win10 machine with default settings:
DCOM Object (Short for Distributed Component Object Model):
is the latest and improved version of COM+ Object, which was originally created in Windows 3.1 under the name "Network OLE".
This object is designed to enable the creation and operation of objects on remote machines.
The communication between the machines is done using the DCE / RPC protocol.
For example, a code that extracts the list of existing DCOM Objects on the local machine:
PS> Function Get-DCOMList {
$path = "REGISTRY::HKey_Classes_Root\CLSID\*"
foreach ($val in dir $path) {
if($val.GetValue("AppID")) {
$CLSID = $val.Name.Split("")|Select -Index 2
Write-Host "CLSID: $($CLSID)"
}
}
}
PS> Get-DCOMList
As well as the output of the DCOM Objects list on the win10 machine with default settings:
That's how you create an Internet Explorer DCOM Object, and extract the interfaces it exports:
This is the list of Internet Explorer object interfaces available on my local machine:
Once we understood how the COM objects work in Windows and how to find and create objects on the compromised/local machine, the following questions are asked:
How can an attacker scan and call functions on the objects accessible in the remote machine?
How to verify whether a specific object exists and is accessible to the attacker?
Does an attacker have access to communicate with an object inside the remote machine?
Of course, in this part Microsoft are trying to make it harder for attackers and have created a defensive array around the issue, wrapping each object under an ACL permissions mechanism. Remember what I wrote above about COM+?
So, what exactly is an ACL? What does it consist of and how does it affect our attack process?
ACL (Short for Access Control List):
is a access list that contains a set of rules about every object that exists in Windows, from a folder, file, to a registry object.
The ACL consists of properties (such as who created the sequence of rules) and DACL and SACL lists.
SID (Short for Security Identifier):
is a unique identifier that exists for each user, service or group in the operating system. This is how a SID looks like: S-1-5-21-3272315122-240233272-2130969425-1000.
Clarification: Whenever I list in the "User" \ "Group" article, I mean the SID directly.
ACE (Short for Access Control Entries):
is an access control record, consisting of a user ID (SID) and a list of permissions that are granted or revoked.
This record is reflected in the DACL and SACL lists.
SACL (Short for System Access Control List):
is a monitoring control list for the system.
That is, the logging mechanism that documented the attempts to access the object.
SACL contains the ACE records that contain the rules about what to monitor when a user accesses an object. For example: User 1 failed attempt to delete.
DACL (Short for Discretionary Access Control List):
is an object access control list, this list contains ACE records that determine which SID may be granted or be revoked to perform any action. For example: Allow access to the Administrators group to view, edit, or delete a specific folder.
Security Descriptor:
is a binary structure that contains many fields, including the owner of the object, and contains the access control (ACL), and indicates the SACL and DACL of an object, as well as other elements that we will not deal with here.
SDDL (Short for Security Descriptor Definition Language String):
is a converted string that consists of the bulk of rules that apply to each SID. Each DACL / SACL list is represented in a string in SDDL format and saved in Security Descriptor format.
So, once we understood some basic concepts, it was time to dive deeper.
We now understand that every object in Windows has a set of rules that permitted or forbidden access to it.
Assuming we do not want to guess if we have access to the object, I wrote a code snippet within the tool (DVS) that indicates and analyzes in advance whether the user we are connected to (or the groups he is a member of), can access a particular object, or alternatively, change the ACL of the same object in order to allow us access to the object (by patching the DACL list). Sounds divine, doesn't it? ☺
So, what exactly does the DVS do?
The tool can scan, validate, and create objects in the remote or local machine, checking whether the user is allowed to create or access existing objects in the remote or the local machine. (by verifying if the user is assigned to the authorized groups or members).
If the user is not allowed to access a particular object, but he is allowed to update the Security Descriptor of that object / default settings, the tool will grant access to the user (SID) and then create the object.
Of course, after the tool has finished its activity on the object (scan or attack), the tool will revert the Security Descriptor to its original form (Housekeeping).
In the scan process, the script will search for functions that the object is externalizing, validating the user’s privileges and it’s ability to execute commands.
This operation will be done by recursive enumeration into the object.
The tool will search for functions using predefined Patterns and Strings, and will verify the feasibility of executing commands by assumptions we will present below.
Here is a code snippet that will search for functions under the main interface of the InternetExplorer.Application object, which contain the sequence of letters "nav":
The list given above consists of Patterns of functions that allow you to execute commands, and Patterns that I think will also fit such functions, but the list can change and it is up to you ☺
In the first phase, the tool will verify whether the function name corresponds to the defined Patterns (i.e. like the list above).
In the second phase (if there is an identification of one of the Patterns you have defined), the tool will verify whether the exported function can enable commands or code execution by verifying the type of arguments the function receives.
Examples that the tool would rule out as vulnerable functions:
void Execute (int)
void Execute (bool)
Example that the tool would consider as vulnerable functions:
void Execute (string)
void Execute (variant)
It can be understood that the tool performs a "premise" and concludes that if we have a function called Execute that accepts only an int (number) argument, we probably will not be able to pass a command line to it.
As I mentioned above, the tool also knows how to attack remote machines using DCOM Object and run external functions / operations on a specific object in order.
The command presents an attack using DCOM Object type MMC20.Application in the network using DVS:
The command above will try to validate our permissions to the MMC20.Application object.
In a scenario that our user is not permitted to access the object, the tool will attempt to grant the users privileges (AutoGrant). otherwise, the tool will attempt to access the object.
Finally, the tool will execute a command using a function called: ExecuteShellCommand.
This will be done at any available IP address, within the address range 10.211.55.1/24, and will be performed when the session of the attacking user (or credentials provided to the tool) is allowed to access the object or via patching the Security Descriptor and then access the object. And after the quick review, here's an interesting issue:
How can we know whether the user we are connected to is actually granted access to a remote object?
How can we retrieve the domain details of the compromised/local machine to diagnose whether the remote machine is associated with the same domain?
First, if we own a user who has access to the remote machine, the tool will perform the following actions:
Try to interact with the Registry in order to retrieve the default or specific rules that apply to the DCOM objects in the remote machine.
First, try remote registry access by verifying the following steps:
Attempt to access port 445
Check if the service is active.
Attempt to interact with the service.
In case of failure, the tool will try to interact with the Standard Registry Provider (StdRegProv)
Attempt to access port 135
Check if the service is active
Attempt to interact with the service.
Attempt to access RegStdProv
Verification is DCOM access possible at all? And if not, can it be enabled remotely?
Verify permissions for the object.
Note: If we do not own a user with access to the remote machine, you can use the "SkipRegAuth" flag, which will set the tool to try to access objects without performing queries and tests against the remote machine.
If you use the tool's scan method (Invoke-DCOMObjectScan), the tool will perform a process of locating and scanning the objects on the remote machine. This process consists of the following steps:
Import the list of available DCOM Objects in the remote machine (if you set it up otherwise, the list will be taken from a specific file or object name that you provide when you run the scan command on the tool)
Checking the feasibility of accessing an object (checking permissions, we will expand on this later)
If we do not have permissions to perform actions, verify that the tool can leave us access
Detecting and validating functions that may allow to execute commands or a code (as we detailed above)
Arranged CSV export with all the following data:
The name of the function found as potential to execute commands or code
The path chain of the function and the list of arguments that the function expects to receive in order
More metadata that can help us explore and research the object that exports the function that meets the criteria we have defined.
So far, we have explained about scanning objects that can be created remotely (DCOM) and locating functions that may be vulnerable according to predefined criteria.
It is important to note that the tool can also execute commands using functions that do not allow commands to be executed directly, by performing manipulations in the Registry (we will expand later in the article ☺). Intriguing, eh?
So how do you know if we have access to DCOM? And where is the Security Descriptor of each object stored?
DCOM config is managed using the GUI interface located in the following path:
%windir%\System32\dcomcnfg.exe
Information about the objects are stored in the register in two different configurations:
List of each specific object (if object-specific rules have been defined)
A list of default rules, which apply to any object for which no specific rules have been set
Enabling and Disabling the DCOM service looks like this:
Disabling and enabling the DCOM service is represented and stored in the Registry by Y / N values, where Y represents active service and N represents inactive service.
It can be understood that even though the DCOM service is inactive, as long as we have editorial access to the Registry, we can activate the service remotely, using Registry access only!
An example of a similar and very familiar scenario from the world of the Pen-Test: Running the RDP service on a remote machine by patching values in the Registry.
The representation in the Registry about the state of DCOM looks like this:
The default rules of all DCOM objects are defined and stored under the following registry values:
MachineAccessRestriction:
Defines the access control (ACL) of which users are granted access to the object and its interfaces when the COM Server of that object is in runtime mode.
These permissions apply to objects that do not use CoInitializeSecurity.
MachineAccessRestriction contains the sequence of rules about each object for which no specific rules have been defined.
If specific rules are applied for a specific object, its rules will be stored in the object tree called AccessPermission, under the entry in the following location:
Local Access defines accessing locally, while Remote Access defines accessing remotely.
MachineLaunchRestriction:
These settings are divided into two layers of security, Launch and Activation.
Activation is the act of gaining access to an object through middleware which mediates between the machine and the object, and defines whether the user is allowed to activate and access a new object.
This occurs when calling CoCreateInstance.
Launch defines who is authorized to run and create a COM Server, in time, an Activation process, if the COM Server of that object is not in runtime mode.
MachineLaunchRestriction contains the sequence of rules about each object for which no specific rules have been defined.
If specific rules are applied for a specific object, its rules will be stored in the object tree called LaunchPermission, under the entry in the following location:
Example of DCOM object activation and launch permissions:
Local Launch determines whether the SID can generate and run a COM Server on the DCOM object in the local machine, while Remote Launch determines whether the SID can generate and run a COM Server on the object via a remote machine. Local Activation determines whether the SID can access the interfaces and functions of the object from a local machine, while Remote Activation determines whether the SID can access the interfaces and functions of the object via a remote machine.
That is, without Activation permission we will not be able to access the object interfaces and without Launch permission we will not be able to create a COM Server to access the object.
The entire process of accessing and identifying with an object that exists in another machine on the network is performed using ORB.
ORB (Short for Object Request Broker):
is used as a middleware that manages the connection to objects from one machine to another machine on the network via RPC.
So far, we have talked about the types of objects in the operating system and the permissions model of DCOM, but how do you even differentiate between DCOM and COM?
From a simple search I did by running the Registry I found that there are +16,000 COM Objects records, and only +400 of them are assigned as DCOM Objects.
To differentiate between objects, we need to understand how an object is represented and stored in the operating system, and what properties apply to it.
A COM object can be identified by the properties stored about it in the Registry, we will expand on 2 main properties:
ProgID (Short for Program ID):
is the name of the object set by the developer in full, for example Nimrod.Levy or an existing InternetExplorer.Application example. You can see the list of ProgID in the registry under the tree: HKEY_CLASSES_ROOT or under the path:
HKEY_LOCAL_MACHINE\Software\Classes
Example of a list of objects for which ProgID has been predefined:
Due to the fact that this name is controlled by the developer, and the developer is not required to define a ProgID for the object there is a probability that there will be conflicts or inability to communicate with the object, so there is another unique identifier for the object called CLSID.
CLSID (Short for Class ID):
is a global and unique identifier of the GUID type, which points directly to the installed object, and contains under its tree in the Registry data such as: the path of the compiled file containing the object functions.
The CLSID list can be seen under the path:
HKEY_CLASSES_ROOT\CLSID
Or under the path:
HKEY_LOCAL_MACHINE\Software\CLASSES\CLSID
Example of a CLASS ID of a DCOM object in the Registry:
So far, we have understood how COM Object is represented in the Registry, so how are COM+ and DCOM objects represented?
Similar to COM+, the DCOM object allows access from remote machines and therefore has another unique representation called AppID.
AppID (Short for Application ID):
is a unique GUID identifier (similar to CLSID), containing a representation of the application that runs as DCOM / COM+ Object, which contains, among other things, the set of permissions to the object and other properties.
Example of an AppID represented in the Registry:
It is important to note that there are situations where the AppID is the same as the CLSID, but this does not always happen, so you must always cross between the AppID and the CLSID in order to extract the CLSID you want to access.
Permissions:
Now that we understand how to identify DCOM Objects, and how the security array is enforced, we can verify whether we are granted to access any object.
But how can we query the remote machine and get the set of rules that apply to an object, if the compromised/local machine is not associated with the domain of the remote machine?
Or is it not associated with a domain at all? How can we query Active Directory through a remote machine without running code through it?
It's time to get into the topic of Active Directory research, and how we can put together the pieces of the puzzle to get an almost certain answer about our permissions ☺ We need to answer a few questions:
Is the remote machine associated with any domain?
If so, is the compromised/local machine associated with the same domain of the remote machine?
Is the attacking machine associated with any domain at all?
If the attacking machine is not associated with any domain or is associated with another domain, how can we identify with the attacking machine?
How to query the attacking machine about users and groups?
After we have a list of questions, it is time to answer the questions in order to build the milestones.
So, let’s get started! Step One, we need to clarify to which domain our user is associated with (or if at all)?
And of course, to which domain is the remote machine associated with (or if at all)? There are several methods to test this, based on the methods applied in DVS.
Before we dive into the methods we can use to query the remote machine, a few words about Active Directory: Active Directory is a Microsoft product that serves as a central identification infrastructure for an enterprise environment, and can also provide a set of ancillary services as needed (file server, communication services such as DNS, WINS, CA server, time server and other services), in the AD environment there are a number of roles for the various components in the authentication servers where the AD database sits on the Domain Controller Servers.
Retrieving the domain to which the remote machine is associated
NBTSTAT command:
This command displays statistics and information about the NetBIOS data of the target computer over a UDP or TCP / IP protocol.
The output will be tables with the machine's NetBIOS information such as computer name, MAC address, domain information to which the machine is connected and record type.
The output can be for both the local computer and for remote computers.
This command also allows you to refresh the NetBIOS name cache and the names listed on Windows Internet (Name Service / WINS).
That is, a refresh will cause the client to re-register the local computer information on the WINS server.
Example of NBTSTAT query against the remote machine:
That is how the request looks like in WIRESHARK:
This is what the response looks like in WIRESHARK:
It is important to note that there is no identification process with the remote machine in order to perform this query, and this operation is not kept in the list of Windows security events, which gives us a significant advantage.
After assuming that it gives us a solution, let's wrap it into code:
This method is great for query remote machines, but the attacker must not depend on that specific method to work, so it is always worthwhile to implement more alternatives, to ensure that the remote query will work in higher percentages.
Using Registry
Assuming we have access to the Registry, there are 2 places that contain the domain name associated under two different Hive according to our privileges (HKLM and HKCU): We will start by searching our domain through regedit to find the relevant places.
The following screenshot shows the domain under HKLM:
The following screenshot shows the domain under the tree in HKCU:
Path: HKCU\Volatile Environment
Once we have found where and how the domain is represented in the Registry, all we have to do is query and compare to the domain of the remote machine.
If the attack machine is not associated with a domain, the next step is irrelevant.
Perform Active-Directory Reconnaissance using the attack machine
Remote machine querying is a widespread topic, but we will focus on the methods applied in the tool. The reconnaissance will only be performed in one of the following situations:
Provided with proper credentials for the domain / attack machine
The attack machine is associated with the same domain
The username and password of the local and used user in the attacker machine are the same as the local user in the remote machine (same username and password)
For example: The attacker process runs by an “Administrator” user whose password is “Aa123456”, and there is such an active user with exactly the same password on the remote machine (you'll be surprised this happens).
When none of the above three conditions are met then the tool will skip the Reconnaissance phase.
The tool uses two main methods to extract information from the remote machine:
If the attacker uses an account (SID) associated with the same domain of the attacker, then the tool will perform all the queries directly in front of the Domain Controller.
Sample code that retrieves groups that a specific user joins using WindowsIdentity:
PS> function Get-UserGroupsUsingWindowsIdentity {
param(
[Parameter(Mandatory = $true)]
[System.Security.Principal.WindowsIdentity]$Token
)
# This function is responsible to resolve SID groups of user (include his user SID)
% {@{GroupName=$Token.Name.Split("")[-1]; SID=$Token.User.Value}}
Foreach($sid in $Token.Groups) {
try {
$groupName = ([System.Security.Principal.SecurityIdentifier]$sid).Translate([System.Security.Principal.NTAccount]).ToString()
# Remove all uppercase groups(INTERACTIVE, SELF, etc.)
if($groupName.Contains("NT AUTHORITY") -or ($groupName -ceq $groupName.ToUpper())) {
continue
}
$global:GroupSIDList[$GroupName] = $sid.Value
%{ $sid.Value }
} catch {
continue
}
}
}
If the attacker uses an account (SID) that is not associated with the same domain of the remote domain, and he wants to obtain information about users or groups in the remote machine he will have to query the domain through the attacked computer using ADSI objects created on the attacked computer and query the DC.
ADSI (Short for Active Directory Service Interfaces):
is a set of COM interfaces used to perform operations on the Active Directory in a programming interface.
ADSI allows you to perform, in accordance with access permissions, administrative operations such as creating and polling users, managing printers, resource information and more, on Windows machines on the network.
Here is a code for retrieving groups from a specific user using ADSI:
PS> Function Get-UserGroupsUsingADSI {
param(
[Parameter(Mandatory = $true)]
[string]$RemoteIP,
[Parameter(Mandatory = $true)]
[string]$Username
)
# This function is responsible to resolve SID of groups that the user is member of using ADSI.
try {
$Account = [ADSI]"WinNT://$($RemoteIP)/$($Username),user"
$groups = New-Object System.Collections.ArrayList
$AccountSID = $account.ObjectSid.Value
if($AccountSID) {
$groups.Add(@{GroupName=$Username; SID=(New-Object System.Security.Principal.SecurityIdentifier($AccountSID,0)).Value})|Out-Null
}
$Account.Groups()|foreach {
$GroupName = ($_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null))
$ObjectSID = ($_.GetType().InvokeMember("ObjectSID", 'GetProperty', $null, $_, $null))
if($ObjectSID) {
$SID = New-Object System.Security.Principal.SecurityIdentifier($ObjectSID,0)
$groups.Add(@{GroupName=$GroupName; SID=$SID.ToString()})|Out-Null
}
}
return $true, $groups
} catch {
return $false, $_
}
}
PS> Get-UserGroupsUsingADSI -RemoteIP 10.211.55.1 -Username Administrator
Excellent! So, we have a way to conduct our queries even from a machine that is out of the domain! But how can we identify ourselves as a particular user when we are outside a domain or part of another domain?
To which DC will the operating system send the identification information we provided to the tool?
What is done to successfully connect to the remote machine, in a script where the attack machine and the remote machine are not associated with any domain, and our compromised/local machine user does not have permission to create a new local user with the same name and password for the tool and password provided to the tool?
How can we identify ourselves as another user? Processes in the operating system inherit the privileges of the process that ran them. This feature creates strange phenomena and extreme cases that are sometimes challenging to explain.
When running Windows tools such as reg.exe (and other tools net.exe, at.exe, sc.exe, etc.)
When running reg.exe inherits the Access Token / Credentials of the processor running it (in this case cmd.exe).
In the classic case, cmd.exe is run by a regular domain user, and will not have permissions to connect to other machines as a local admin so all reg.exe calls to remote machines will fail.
What is surprising is that in this scenario, when the machine is associated with the same domain, even if we make an IPC$ connection using a username that is an admin domain as follows:
net use \\domain_controller\IPC$ /user:domain\domain_admin
All operations will still fail, direction and net.exe will inherit the permissions of the cmd.exe that ran it and will completely ignore the username we entered in the command prompt.
In the following screenshot, the user connected to the attack machine is the “Donatello” user in the “Atlantis” domain.
This user is a regular user, with no administrative privileges on other machines in the domain.
The screenshot shows a successful connection to the WIN-IVPFLNTUF20 machine with another user with Domain Admin privileges. Although the connection is successful, all subsequent readings fail.
The failure is due to the fact that the reg.exe is run by the user “Donatello” and therefore does not inherit the privileges with which we connected by net.exe.
When the parent process (cmd.exe) runs with a local user (not associated with a domain), then the operating system will use the permissions specified in the command line and we will be able to access the remote resource with the user we connected through the command line (atlantis.local\shredder - Domain Admin).
It can be deduced from the example above that this scenario only responds to an end state where we run through a local user, but does not respond to all end scene, for example, a scenario where the user through which we run the process is associated with the same domain, and is not allowed to perform the actions we need perform, because the processor will always run under the permissions of the user who created it.
Next, we thought of performing impersonation in order to configure another temporary user to run a process, which may perform the required operations on the remote machine. But this action is problematic as well, and we will explain why:
Impersonation is a security concept implemented in WindowsNT that allows the process to temporarily identify itself as another user.
This action is for Windows to perform actions through another user without logging in to perform certain actions.
The disadvantages of the concept are:
There are a number of extreme situations in which we will not be able to "impersonate" another user, such as:
If the attacker machine is not associated with the domain of the remote machine.
If the attacker machine is not associated with the domain in general.
The remote machine is not associated with the domain in general.
Too noisy - this produces a lot of problematic logs, and usually indicates an attack.
Requires high permissions for the compromised/attacker user.
Performing impersonation requires the following permissions from the user:
SE_TCB_NAME
SE_CHANGE_NOTIFY_NAME
SE_ASSIGNPRIMARYTOKEN_NAME
As you understand, impersonation may impart only a partial solution (due to all the extreme situations we will have a hard time dealing with).
In theory, I was looking for a concept that would be a solution to the following issue:
Once we access a remote machine, that remote machine will require us to identify with it in any way, the compromised/local machine will attempt to use the pre-defined credentials(username/password) that have been set in the script execution and transfer them to the remote machine without going through any identification system. (assuming the credentials were provided to the tool).
After much thought, on how I could implement the theory, I thought a bit about how tests are performed on customers' infrastructures and remembered that there is a solution to the problem!
Using RunAS in combination with the flag “netonly” allows us to run under our user's profile, and send predefined identification details, in any connection with an external machine, without verifying the credentials defined in front of the identification mechanism!
What is RunAS? What does the flag represent netonly?
RunAS is a command in the operating system line, which allows the user to run specific tools and programs under a different user profile than the one used to log on to the computer interactively.
The flag “netonly”, configures RunAS not to attempt to validate the credentials submitted by the RunAS command (as opposed to not using this flag).
In fact, if the "netonly" flag is used, the command will create a new process that will use the current and interactive session of the user through which we run, but will submit the credentials defined in the RunAS command only as soon as some identification to a remote machine is required.
That is, the action that takes place behind the scenes, is sending the defined credentials only when turning to a remote resource that we will perform, and thus we resolve the issue: failure of a validation process using the credentials provided to the tool.
It is important to note that if we are attacking the local machine, and indeed we want to perform the attack using other identification information, we must perform the RunAS process without using the “netonly” flag, since the “netonly” flag is only valid for communication outside the machine.
The following screenshot shows a successfull attempt to access the Remote-Registry:
Note: This Session created via RunAS that has been configured with credentials of a user with high privileges on the compromised/local machine, using the “netonly” flag.
Kawabanga!! We have solved all the end modes mentioned above! But another problem arose...
The problem is that now everyone who uses the script needs to be defined, understand the situation in which he finds himself, and from that choose whether to use RunAS, and whether to use the flag “netonly”.
What if the attacker is inside a computer that has gained access to it? A little annoying... So how do we solve this?
I changed the behavior of the script a bit, and wrote another code snippet that would examine the situation we are in, according to which he would choose whether to use RunAS (using API Calls of course), and know how to decide for himself whether to use the flag netonly, under a hidden process.
If RunAS does not need to be used (for example, no identification information was provided), the script will create a hidden process with the current permissions so as not to break the Design.
The script in the running process is divided into two:
NamedPipe Server
NamedPipe Client
The server runs as a hidden process, and will act as an Agent who will perform all active actions in front of the attacking machine.
The client runs as a frontal script (the one you run and through it you will also see logs), and will be the decision maker, and will transfer tasks to the server.
After performing each task, the Server returns the answer to the Client.
The two processes will communicate with each other using NamedPipe.
What is NamedPipe? In computer science, inter-process communication (IPC) is a collection of methods and mechanisms for transferring data between processes within the same process or between different processes (Wikipedia).
Think of a situation where we want to call between 2 processes in the same machine (or in a remote machine, it is also possible), quickly.
NamedPipe is basically a concept that allows you to define a communication file which knows how to transfer traffic between 2 processes.
Communication is conducted solely in a situation where the Server and Client are listening at the same time.
If one side is not listening, the pipe will wait until the other side is connected.
Cool, now the code works, and knows how to perform all our operations, but what can be done in situations where COM objects is not respond? Lots of tools solved this in the form of a list of problematic DCOM objects.
Sounds less cool to update blacklist lists all day, so I wrote another code snippet that knew how to run the operations in front of the objects within a thread with a predefined timeout.
If the operation occurred within the set time frame, the response from the Server will be returned to the Client, otherwise, a negative response will be returned. Example of a scenario where the COM Object is unresponsive:
When you turn on a Word.Application object, for example, and the Word application has never opened, you will see the Office Welcome message pop up, and until you define it the COM will not be able to function.
So far, the instrument is playing cool.
But what happens if I have access to perform the Reconnaissance and it appears, I do not have access to the object (DACL)?
After the ACL analysis, if we do not have permission to access the object, but we have permission to patch the Security Descriptor, the script will make a copy of the current ACL (Clone), check if our SID appears with any prohibitions in the list, if and prohibitions apply to us, the script will remove them and allow us the relevant permissions in order to communicate with the relevant object.
After the process of changing the ACL and adding the permissions we need to communicate with the object, the script will patch the Security Descriptor of the relevant object or the default with the new ACL.
Of course, after completing the activity in front of the object, the script will revert the Security Descriptor to the same state it was in before the patching process.
Great, everything works!
But what if we scanned, and we do not have a DCOM Object with functions that allow us to run commands? Or another situation, we do not have the appropriate permissions? Can't we run commands? The answer is no ☺
Invoke-RegisterRemoteSchema
After in-depth research, and consulting with Rafi, we found a solution where we can use DCOM Objects that do not contain functions that allow to run commands, and do not require high privileges, and through them, combined with manipulations in the Registry we can run commands!
We called the method Invoke-RegisterRemoteSchema and as its name implies.
The idea was to create a new schema, which will know how to run commands as soon as they are called (such as http:// or ftp://).
We dived a bit to see how schema is represented in the machine? How can we use it?
We went to regedit and searched for a known schema (e.g. http), and here are the results:
Does it also feel like something you can work with? ☺
Our theory was this, look for DCOM Objects that contain functions that allow you to route between folders and files, and use them to route to our schema which will contain the command we want to run.
In the script you will see the final PoC, here is just a small example.
First, we'll try to execute a calculator, using a new schema we'll create, and try to keep it under current user, so that we can do this with the lowest permission.
We will export to the entire tree of the http scheme, and we will start making some minor changes for the test.
The changes made are:
Change the hive from HKEY_LOCAL_MACHINE to HKEY_CURRENT_USER to run at low permissions
Change the scheme name from HTTP to DVS
Defining a payload that knows how to take an order from the content after the scheme (everything that comes after dvs://).
Once we import to the new registry key, we have to run the following command in Run:
dvs://cmd /c calc
It looks like something that we can work with.
Now, we will combine the capabilities of the script, all the objects containing the following Patterns: Navigate* and Open* will be found and stored inside the vulnerable.txt file, and then we will run the following command:
Since scanning the entire machine does not take a few minutes, meanwhile, until the end of the scan, we will open Internet Explorer, and run the following line:
dvs://cmd /c calc
As you may have noticed, a warning pops up that looks like this:
We will sample the Registry (for example using regshot, but it is also possible with a process monitor and see the changes there as well), uncheck the box "Always ask before opening this type of address" and click Allow.
Then, we will sample the Registry again and see the differences (whoever ran the process monitor will have to look for the changes in the Registry after the interception). After checking it can be seen that a value named ds has been added in the following path:
After adding the record, with the value: 00000000x0, the warning box will not pop up and we will run a calculator! ☺
It is also important to add entries to the Registry if this is the first time the attacking machine is running Internet Explorer, but we will not address it here, you can read the above lines of code directly from the GIT. Let's try running the following command:
Of course, the tool knows how to perform the whole process specified in the article and more correctly (using the Invoke-RegisterRemoteSchema function via the DVS tool), and clean the attacked machine at the end of the command (Housekeeping).
The tool also contains 4 different types of DCOM that are vulnerable to this scenario (the list is shown above).
It is important to note that the script will verify that the connection with the object has been made in full in front of the remote machine.
And if the operation is not fully performed, the script will skip to the next vulnerable object. Notice: the script will configure Internet Explorer if it has never been configured!
Here is an example of running the Invoke-RegisterRemoteSchema module using the tool:
Good, cool! We talked about scanning, we talked about attack...
Rafi and I are soon planning some more substantial updates to the script with all sorts of cool detours! It's time to talk a little bit about defense.
Identification and Prevention
Following the research done on the existing capabilities today to identify and protect against the methods applied in DVS tools, we came to the conclusion that turning off DCOM access through the Component Services interface is not sufficient, and this is due to the fact that as mentioned above, the tool knows how to enable remote access This type of object is an essential, legitimate and integral part of the operating system (in the context of an attack, we define this scenario as Living-Off-The-Land)
Living-Off-The-Land
This combination of words describes a situation in which we survive from what exists on the ground.
When this statement is taken to the technological world, it is meant that an attacker can use tools and interfaces that already exist in the victim's infrastructure and operating system, and use them to perform malicious actions legitimately, thus evading monitoring systems.
Here is a link that shows information and examples of running malicious code using existing tools in the operating system:https://github.com/LOLBAS-Project/LOLBAS
So, what can be done, and what events does the operating system produce?
In order to address this issue, it is necessary to protect and monitor the protocol in several different layers and security circuits.
The idea of security circles is no stranger to people who work in airport security nor to people who manage and take part in protecting an enterprise network from the keyboard.
The need to perform the protection in stages and layers also stems from the fact that tools like DVS can undo the hardening we have performed and therefore we need to perform both identification of this action and not just enforcement.
As with other attacks, a network attack using DCOM Objects also leaves suspicious marks that can be used to conclude that a network attack scenario has been performed.
Here are some examples that can give an indication that such an attack has been carried out on the network or on the local machine:
Events that appear in the Operating System Event Log.
Information that is within the network traffic.
Suspicious behavior of creating processes at end stations.
In order to perform a proper protection process, we will split the protection procedure into three layers:
Prevention
Protection
Identification
Prevention
The tool can be prevented from performing malicious actions by disabling the capabilities it utilizes.
That is, reducing the attack surface. As an example, to the physical world - instead of holding a building with several wooden doors, we will remove or block all the wooden doors in order to leave a lower amount of entry options in effect.
Here are some simple steps you can take to reduce the attack surface:
Disable Remote Registry
This is a general hardening recommendation even regardless of neutralizing this lateral movement technique.
If this protocol is not used and this protocol is active, it is highly recommended to turn it off.
It is important to note that DVS uses the Remote Registry for several operations. When this protocol is enabled, the attacker has the ability to run code on the machine, change firewall rules, allow access to DCOM, and the list goes on.
How to disable Remote Registry through Active Directory:
Disable the DCOM protocol
Disabling the DCOM protocol is an essential step in neutralizing lateral movement using DCOM Objects, and this is because there is simply nowhere to connect.
This is a toughness that is not applicable in the vast majority of organizations. This is because sometimes there is dependence on these objects by different services.
And yet, this option is great for extreme cases like isolated stations, kiosks, etc.
One of the most common management tools used by DCOM is WMI (Short for Windows Management Instrumentation).
It is a legitimate tool that exists in the operating system which allows to run various local or remote commands and get information back.
It is also important to note that if there is access to the Remote Registry or WMI, the DVS can turn on the protocol remotely!
The following screenshot shows how to disable DCOM Access via the Component services (dcomcnfg.exe):
Using LAPS
Microsoft has given a great solution in order to reduce the attack surface. When an attacker is holding machine A, he will not be able to use the same identification details of the local manager in order to make a transverse movement to machine B.
This is because this protection produces different passwords for the same username on different machines.
What is the LAPS mechanism?
Abbreviations: Microsoft Local Administrator Password Solution.
It is a password management mechanism that manages and exchanges passwords for local administrator accounts at all end stations connected to the domain.
This provides a solution to increase privileges and cross-sectional permissions using a local administrator credentials found on a machine.
By using a GPO, you can distribute to the entire organization a set of rules and permissions that will be defined at the end stations.
An organization can revoke access to other machines on the network through a specific user or group by revoking the "Access this computer from the network" permission.
Alternatively, a group can be created that will allow access to network administrators and users who need access to remote end stations, thereby lowering the exposure and vulnerability surface.
Interesting fact: CIS's official recommendation to harden Windows10 allows for a number of vulnerabilities that the tool exploits
The following screenshot shows a group holding the list of those authorized to connect to computers remotely:
Hardening DCOM privileges
As explained at the beginning of the article, Microsoft has created an array of permissions that addresses the approval and blocking of access to objects through the Component Services interface.
This interface allows you to define who is allowed to create and access an object remotely, and this setting can also be applied by a GPO.
The following screenshot shows an example of changing the default settings of DCOM objects that have no specific rules defined for them:
Protection
Activate the Microsoft Defender firewall on the endpoint:
It is important to note that when the Remote Registry is enabled, the firewall restrictions can be changed, leaving remote access to this protocol.
When defining the firewall, profiles can be activated that will provide blockage against the DCOM protocol from remote machines and thus provide a lateral traffic protection surface using DCOM.
Most often, organizations put out the local firewall for one reason or another and therefore remain vulnerable to attack.
The following screenshot shows an example of a future update that DVS can make! The tool will know in the future to allow access to a particular protocol, even if you blocked it! All this at a discount and there is read and write access to the Registry via WMI or Remote-Registry:
Identification
GATEWAY Monitoring:
In order to get identification marks at the level of network traffic, you can use the GATEWAY product that knows how to detect DCOM traffic and allows you to set a set of rules that will prevent or leave access.
There are possible open-source solutions like SNORT or SURICATA or other off-the-shelf solutions.
These tools allow you to monitor events at Windows endpoints by collecting EVENT LOGS of several types that include: station identification events, process creation, and DCOM errors.
The following screenshot shows events that indicate attempts to create a DCOM object without the appropriate permissions:
You can monitor REGISTRY changes:
Examples:
New rule created in Windows Firewall
Run DCOM that is off and create a new object.
These changes can indicate tools like DVS that try to bypass toughening and operating system protections.
Registry monitoring is a necessary step in order to identify Registry readings and changes designed to overcome and circumvent the toughness and protection measures.
Anomaly detection at the end station
Another compensatory control we can take into account - process-level anomaly monitoring.
This method provides a solution in general and not just for attacks related to DCOM.
Today there are endpoint protection products that can detect these anomalies and even block them (e.g. EDR)
An example of an anomaly that systems like EDR could detect: Run a process like Outlook.exe that will run a cmd.exe process underneath.
The problem
There are many objects attacking by objects, and there may be objects of different software between one organization and another organization, therefore, this method of identification is not accurate enough.
Here's a cool example where we'll try to avoid EDR, by changing the anomaly:
We will create a DCOM Object of type Outlook.Application
Through it we will create a "bridge" to the COM Object of the Shell.Application method
Run cmd through the ShellExecute function exported from the Shell.Application object
This scenario will be more difficult to identify because in terms of EDR, additional steps were added before running the command.
Instead of the usual scenario where a DCOM Object of type Outlook runs cmd, we created a new scenario where DCOM Object of type Outlook creates a COM Object of the Shell.Application type (which also puts RuntimeBroker into the mediation process, remember what I wrote about ORB?), And then runs explorer.exe.
The explorer.exe runs cmd.exe through one of the ShellExecute functions exported from the Shell.Application COM object.
As can be understood, the defense and attack teams are in a kind of "cat and mouse" game, but today there are quite a few means of identifying such actions, which can facilitate the defense teams.
For example:
Application Control Rules
SYSMON
OSQUERY
What are OSQUERY and SYSMON and what is the difference between them?
SYSMON allows you to create a set of rules for suspicious events that we want to know about if and when they happen.
OSQUERY, on the other hand, allows you to gather a lot of information from the operating system on which it is installed.
You can perform queries in front of the OSQUERY, and get an answer about specific information in the operating system. With the help of OSQUERY we will be able to ask which processes are in runtime and who created them.
Conversely, if we create a law in SYSMON, we can create an event when a sequence of actions we have defined has occurred.
Just as DVS gives a solution of efficient and cunning lateral movement to the attackers. DVS can also be used by a defense team that wants to actively examine itself and know if the organization is vulnerable to this attack, and if it knows how to deal with, identify and stop it.
The technological development of potential attackers of both the good and the bad kind, forces organizations to evolve and change the defense methodology.
There is a growing need to conduct independent and active testing according to the Purple Team method, in which there is full cooperation between the attacking team and the defensive team, thus improving the ways of identifying and preventing such attacks.
Thanks To,
Many thanks to Refael Ivgy (Rafi) for helping in designing the script and writing the article.
Also, many thanks to Tal Zucker and Lavi Ben Baruch for helping to edit the article, and to Gleb Glazkov in writing the protection and monitoring sections.
The author
Nimrod Levy - Information Security Researcher and CTO at Scorpiones.
For questions you can contact me by email: [email protected]
Is your infrastructure resilient against the most advanced network-level attacks?
Let our team test your network, we will identify and patch exploitable vulnerabilities in your systems, verifying your network is resilient against cyber attacks.
Contact us now!