I'm working on security "sandboxing" an out-of-process COM server developed by a different company, so that it runs through a restricted user account with limited access to the local disk. The sandboxing must be configured programatically, so that it cannot be overridden by tweaking registry entries.
I'm already able to impersonate a different user in the client thread though LogonUser
and ImpersonateLoggedOnUser
. I'm also attempting to initially disable COM security, just to get things up & running. However, CoCreateInstance
always fails when passing CLSCTX_ENABLE_CLOAKING
to enable user impersonation.
#include <atlbase.h>
CComPtr<IUnknown> CoCreateAsUser (wchar_t* progid, wchar_t* user, wchar_t* passwd) {
// initialize multi-threaded COM apartment
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
abort();
// impersonate a different user
CHandle user_token;
if (!LogonUser(user, L""/*domain*/, passwd, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &user_token.m_h)) {
auto err = GetLastError(); abort();
}
if (!ImpersonateLoggedOnUser(user_token)) {
auto err = GetLastError(); abort();
}
// attempt to disable COM security and enable cloaking
HRESULT hr = CoInitializeSecurity(nullptr, -1/*auto*/, nullptr, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_STATIC_CLOAKING, NULL);
if (FAILED(hr))
abort();
// create COM object in a separate process (fails with 0x80080005: Server execution failed)
CComPtr<IUnknown> obj;
hr = obj.CoCreateInstance(progid, nullptr, CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING);
if (FAILED(hr))
abort();
return obj;
}
The problem can be reproduced by e.g. calling CreateAsUser(L"Excel.Application", username, password)
to attempt to launch Microsoft Excel through a user other than the currently logged in. This will trigger the same failure as observed with my custom COM server.
CoCreateInstance always fail with hr = 0x80080005: Server execution failed
, either immediately, or after 30 seconds. Futhermore, the Event Viewer will log The server {00024500-0000-0000-C000-000000000046} did not register with DCOM within the required timeout
in the System event log.
Diagnostics from Process Monitor: The COM server process is spawned with the correct user, but it exits immediately with exit code -1073741502 (STATUS_DLL_INIT_FAILED). The environment variables seem to have been inherited from the parent process, and are not impersonated. This leads to mismatch between the user and environment variables.
My COM security experience is rather limited, so don't really understand how to make this work.
User contributions licensed under CC BY-SA 3.0