Bogudan
Bogudan

Reputation: 121

How to fix IWbemLocator::ConnectServer returning E_ACCESSDENIED?

My goal is simple: to establish a WMI connection to a remote machine. A small test program shows that what was working since the WinXP era is now outdated. With WMI hardening update, WMI clients are expected to use the RPC_C_AUTHN_LEVEL_PKT_INTEGRITY authentication level. But just changing it in code, apparently, does not solves the problem.

Test setup:

Given the following code:

// Compile with cl /std:c++17 or later
#include <wbemcli.h>
#include <string_view>

#pragma comment (lib, "wbemuuid.lib")
#pragma comment (lib, "ole32.lib")
#pragma comment (lib, "OleAut32.lib")

#define IP      L"192.168.1.2"
#define LOGIN   L"Administrator"
#define PWD     L"P@ssw0rd"

using namespace std::literals;

::BSTR SysString (std::wstring_view data) {
    return ::SysAllocStringLen (data.data (), (UINT) data.size ());
    }

int main (void) {
    ::wprintf (L"CoInitializeEx -> 0x%08X\n", ::CoInitializeEx (nullptr, COINIT_MULTITHREADED));
    ::wprintf (L"CoInitializeSecurity -> 0x%08X\n", ::CoInitializeSecurity (
        nullptr, -1, nullptr, nullptr,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE,
        nullptr, EOAC_NONE, nullptr
        ));
    ::IWbemLocator *wmiLocator = nullptr;
    ::wprintf (L"CoCreateInstance -> 0x%08X\n", ::CoCreateInstance (
        CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER,
        IID_IWbemLocator, (void **) &wmiLocator
        ));
    if (wmiLocator) {
        ::IWbemServices *pNamespace = nullptr;
        ::wprintf (L"ConnectServer -> 0x%08X\n", wmiLocator->ConnectServer (
            SysString (L"\\\\" IP L"\\root\\cimv2"sv),
            SysString (IP L"\\" LOGIN L""sv),
            SysString (PWD L""sv),
            nullptr, 0, nullptr, nullptr, &pNamespace
            ));
        if (pNamespace)
            pNamespace->Release ();
        wmiLocator->Release ();
        }
    return 0;
    }

I get the following output:

CoInitializeEx -> 0x00000000
CoInitializeSecurity -> 0x00000000
CoCreateInstance -> 0x00000000
ConnectServer -> 0x80070005

Also, on the target machine, an event with the code 10036 gets created (the one about client applications requiring at least RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) with both valid and invalid passwords.

I also tried setting RPC_C_AUTHN_LEVEL_PKT_INTEGRITY instead of RPC_C_AUTHN_LEVEL_PKT_PRIVACY, with the same result.

Upvotes: -1

Views: 205

Answers (1)

Igor Levicki
Igor Levicki

Reputation: 1614

I used 4 machines for testing:

  1. Domain-joined Windows 11 workstation
  2. Windows Server 2022 which is a PDC for domain-joined Windows 11 workstation
  3. Standalone Windows 11 workstation (first VM)
  4. Standalone Windows 7 SP1 workstation (second VM)

I tested the following scenarios with your code:

  • 1 -> 2 using Domain Administrator account — SUCCESS
  • 1 -> 3 using Local Administrator account — SUCCESS
  • 4 -> 2 using Domain Administrator account — FAILURE
  • 4 -> 3 using Local Administrator account — FAILURE

Even after configuring computer-wide DCOM security level to Packet Integrity using dcomcnfg.exe on Windows 7 SP1 and restarting the connection was still being denied.

Based on test results it seems that Windows 7 SP1, for which Microsoft has not released a DCOM Security Bypass hotfix (a fix for CVE-2021-26414), is uncapable of connecting to computers running operating systems which have received this hotfix.

To make sure that your code isn't the problem, I have also tested from Windows 7 SP1 using WMIC command line tool and it fails with the same error even if you specify /authlevel:Pktintegrity along with correct credentials.

For more details, see this Microsoft KB article (check the OS table to see the relevant hotfix KB numbers for each of them).

TL;DR — Your code should work from a different client OS, but if you need it to work from Windows 7 SP1 then you seem to be out of luck.

Upvotes: -1

Related Questions