Google Cloud Preventing users from requesting Windows credentials on GCP

After you have created a Windows VM on Google Cloud, you can use the Set Windows password button in the Cloud Console or the Generate Windows logon credentials function in IAP Desktop to request login credentials. You can then use these credentials to log on to Windows as a local administrator over RDP or any other channel.

IAP Desktop

The logic to generate credentials is implemented in the Compute Engine agent: when requested to generate credentials for a certain username, the agent first checks if there is an existing user account with that username. If the agent finds an existing user account, it resets its password, otherwise it creates a new user account and adds it to the local Administrators group.

Generating credentials requires the Compute Instance Admin IAM role and, if the VM has a service account, the Service Account User IAM role. Interestingly, it’s not the agent itself that performs the permissions check – instead, the permission check is done indirectly: to trigger the agent to generate credentials, you have to modify the VM’s metadata – and to modify a VM’s metadata, you need the aforementioned permissions/roles.

Risks

Local Windows administrator accounts have a bad reputation in the security community, and there are multiple reasons for that:

  1. Local administrator accounts often have the same password across entire fleets of machines. Such shared credentials enable lateral movement within an environment: once an attacker has taken over one machine, they can use the shared credentials to log on other machines.
  2. Local administrator accounts typically do not “belong” to any particular person and are therefore not subject to any automated joiners/movers/leavers processes. Not being subject to any cleanup process means you might end up with “orphaned” administrator accounts.
  3. In an Active Directory environment, local administrator accounts can be abused to dump credentials of logged-in domain users. These domain credentials can then be used to attack domain resources.

When you request credentials, Compute Engine allows you to choose a username, but it does not allow you to choose a password – instead, the Compute Engine agent generates a random password for you. This behavior might seem inconvenient, but it is an important security feature: although multiple VM instances might end up with local administrator accounts sharing the same username, it is unlikely that the randomly generated passwords of these accounts match. This behaviour therefore minimizes the first risk.

But what about the other two risks?

If the Compute Engine agent creates a Windows user account, then the user account is not connected in any way to the Google Cloud user who requested its creation. That means:

  • The lifecycle of the two accounts (Windows user account, Google Cloud user) are disconnected: if the Google user loses access to the Google Cloud project, or the user account is suspended or is deleted, the local administrator account remains unaffected and stays active. Unless there are other protections like Identity-Aware-Proxy in place, this disconnection can lead to a situation where people retain administrative access to VMs after having left the company.
  • A Google Cloud user with Compute Instance Admin access to the respective instance can not only reset their own Windows user account password, but any Windows user password.

Given all these risks, it obviously makes sense to limit the use of local administrator accounts.

In a non-Active Directory environment, eschewing local administrator accounts is typically not an option. Still, you can limit the number of local administrator accounts (and thus, the risk that comes with them) by:

  • Reducing the number of users in the Compute Instance Admin role.
  • Periodically scavenging local administrator accounts.

In an Active Directory environment, local administrator accounts pose an increased risk as they can be abused to dump credentials of logged-in domain users (see item 3 above), but they are also less essential. In such an environment, it can be best to prevent users from generating credentials by disabling the feature entirely.

Mitigation

The component of the Compute Engine agent handling credentials is called the account manager and there are two ways to disable it:

  • You can add a metadata key disable-account-manager to the instance or project-wide metadata and set it to true.
  • You can create a C:\Program Files\Google\Compute Engine\instance\configs.cfg INI file and add the following section:

    [accountManager]
      disable = true
    

If your entire Active Directory environment only spans a small number of Google Cloud projects, or if you’ve fully automated project creation, then adding the respective metadata key to all projects is a good option. But the more projects your Active Directory environment spans, the higher the risk that one of the projects lacks the key, or that somebody removes the key.

To ensure that the account manager is disabled for all domain-joined machines, regardless of the project they are deployed in, it is typically better to rely on the INI file and to control it by using group policy:

  1. In the Group Policy Management Console, create or select a group policy object and select Edit.
  2. Navigate to Computer Configuration > Preferences > Windows Settings > Ini Files
  3. In the right window pane, right click on the empty list and select New > Ini File.
  4. In the menu bar, click the +.
  5. In the New Ini File Properties dialog, configure the following settings:
    • Action: Update
    • File Path: C:\Program Files\Google\Compute Engine\instance_configs.cfg
    • Section Name: accountManager
    • Property Name: disable
    • Property Value: true
  6. Click OK.
  7. Close the Group Policy Management Editor window.

Keep in mind that Group Policy treats INI file settings as a preference, not as a policy, so the file will stay in place even if the Group Policy object goes out of scope.

Thanks to Marco Ferrari for reviewing this blog post.

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home