Home > Blockchain >  Can't open thread token of NamedPipe client: "Cannot open an anonymous level security toke
Can't open thread token of NamedPipe client: "Cannot open an anonymous level security toke

Time:02-20

I am trying to impersonate a client with SYSTEM privileges.
I noticed that this client it trying to connect to the named pipe: \\.\pipe\abc.

I setup a named pipe server \\.\pipe\abc and wait for it to connect.
Once it was connected, it failed:

[ ] Creating pipe server
[ ] Waiting for client to connect
[ ] Client connected
[ ] Client impersonated!
[ ] Failed to get thread token! 1347

The error 1347 according to Microsoft:

ERROR_CANT_OPEN_ANONYMOUS

1347 (0x543)

Cannot open an anonymous level security token.

Why did it happen? It succeeded to impersonate but then failed to open the thread.

This is my code until the failure on OpenThreadToken.

SECURITY_ATTRIBUTES SecurityAttrs = {
      sizeof(SECURITY_ATTRIBUTES),
      NULL,                               // assigned access token of calling process
      FALSE
  };

  DWORD openMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_OWNER;
  DWORD pipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;

  std::cout << "[ ] Creating pipe server\n";
  for (;;) {
      // create the named pipe
      HANDLE pipe = NULL;

      DWORD msgSize = 1024;
      pipe = CreateNamedPipeA(
          "\\\\.\\pipe\\abc",
          openMode,
          pipeMode,
          1,              // max instances
          msgSize,        // out buffer size
          msgSize,        // in buffer size
          0,              // timeout. 0 ~= 50ms
          &SecurityAttrs);

      if (pipe == INVALID_HANDLE_VALUE) {
          DWORD err = GetLastError();
          std::cout << "[!] Pipe creation failed! " << err << std::endl;
          return err;
      }

      // wait for client to connect
      std::cout << "[ ] Waiting for client to connect\n";
      bool connected = ConnectNamedPipe(pipe, NULL) ? true : (
          GetLastError() == ERROR_PIPE_CONNECTED);
      if (!connected)
          continue;
      std::cout << "[ ] Client connected\n";

      // read from pipe
      char buf[msgSize];
      DWORD bytesread = 0;
      bool status = ReadFile(
          pipe,
          &buf,
          msgSize,
          &bytesread,
          NULL);

      // impersonate the connector
      if (!ImpersonateNamedPipeClient(pipe)) {
          DWORD err = GetLastError();
          std::cout << "[!] Impersonation failed! " << err << std::endl;
          return -1;
      }
      std::cout << "[ ] Client impersonated!\n";

      HANDLE hToken = {};

      if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, &hToken)) {
          DWORD err = GetLastError();
          std::cout << "[!] Failed to get thread token! " << err << std::endl;
          return err;
      }

CodePudding user response:

According to OpenThreadToken,

If the token has the anonymous impersonation level, the token will not be opened and OpenThreadToken sets ERROR_CANT_OPEN_ANONYMOUS as the error.

And According to Impersonation Levels,

The client of a named pipe, RPC, or DDE connection can control the impersonation level. For example, a named pipe client can call the CreateFile function to open a handle to a named pipe and specify the server's impersonation level.

When the named pipe, RPC, or DDE connection is remote, the flags passed to CreateFile to set the impersonation level are ignored. In this case, the impersonation level of the client is determined by the impersonation levels enabled by the server, which is set by a flag on the server's account in the directory service. For example, if the server is enabled for delegation, the client's impersonation level will also be set to delegation even if the flags passed to CreateFile specify the identification impersonation level.

Your named pipe client do need to call the CreateFile function to open a handle to a named pipe and specify the server's impersonation level.

CodePudding user response:

based on comments, in client code -

FILE_FLAG_OPEN_NO_RECALL | FILE_FLAG_OVERLAPPED;

used if place dwFlagsAndAttributes in call of CreateFile

however need notice that FILE_FLAG_OPEN_NO_RECALL == (SECURITY_SQOS_PRESENT|SECURITY_ANONYMOUS) and FILE_FLAG_OPEN_NO_RECALL == SECURITY_SQOS_PRESENT

both this flags have the same binary value 0x00100000 (and SECURITY_ANONYMOUS == 0 )

think this is problem of design of CreateFile api. it have less parameters, compare NtCreateFile and it try combine different parameters in single. for instance in single dwFlagsAndAttributes combine FileAttributes CreateOptions ObjectAttributes->SecurityQualityOfService . so parameter is "overloaded"

  • Related