When you add a new computer, it must first join the domain. If you use its future main user to do it, they’ll become the owner and be able to hijack the computer to become a local administrator in four easy steps.

During internal assessments in Active Directory environments, we often use BloodHound to find privilege escalation paths and we happen to find users with a GenericAll relationship to their own workstations. This often means the IT joined these computers in a non-recommended way.

GenericAll relationships are an open invitation to become local administrator on the computers once the users are compromised.

Joining Computers to a Domain

By default, any authenticated user can join up to 10 computers to the domain. The GPO configuration Add workstation to domain defines who can join computers (Authenticated Users by default), the maximum computer each user can add being defined by the property ms-DS-MachineAccountQuota (10 by default).

When computers are joined to the domain that way, the account that joined it is granted several privileges on computer object (such as GenericAll).

In order not to give these privileges to normal users, it is recommended to use a dedicated account with the sole purpose of joining computers to the domain. It should have the Create Computer objects right on the corresponding organizational unit (OU). When computers are joined by this account, different privileges are assigned on the computer object (Owns in BloodHound) and the graph look like this:

Although the privileges granted in the one or the other case are not the same, the account that joined the computer to the domain can gain administrative privileges on it.

Exploitation

In order to gain administrative privileges on the computer, the account that joined it to the domain has to use so-called Resource-Based Constrained Delegation. This technique has already been extensively described on the Internet, for additional details, see the references at the end of this post.

Basically, it consists of four steps:

  1. Gain access to an account – let’s call it JOIN – who has GenericAll or Owns privileges on the victim computer – called VICTIM.
  2. Gain access to a computer account – called HELPER – e.g. by creating a new one with any Authenticated User or with JOIN, or by becoming local administrator of another computer.
  3. Use JOIN to modify the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of VICTIM and set it to trust HELPER. This will allow HELPER to impersonate domain users when handling with VICTIM.
  4. Use HELPER to connect to VICTIM and impersonate a user who can be delegated and who is a local administrator on VICTIM, e.g. a domain administrator.

Remediations and Best Practices

In order to prevent this kind of exposure, you’ll have to prevent users from joining computers to the domain and use a dedicated account instead. First, remove the Authenticated Users from the GPO configuration Add workstations to domain (SeMachineAccountPrivilege):

Then, change the ms-DS-MachineAccountQuota attribute from 10 to 0:

Now, you can create a dedicated account with sole purpose and permission of joining computers to the domain by granting it the permission Create Computer objects on the corresponding OU or by using the Delegation of Control Wizard:

This account should have a strong password, that is changed regularly and that should only be known to administrators with regard to the permissions it confers.

Finally, you should protect every account with administrative privileges in general by setting the option Account is sensitive and cannot be delegated. This can break things if you use (un-)constrained delegation with these accounts.

Fix What’s Already Done Wrong

Once this is in place, you might want to find the users with privileges on their computer due to previous practices and remove the permissions on the computer object.

To do so, you can use BloodHound to assess the situation. Once you have loaded the data from your domain in the application, mark the known and trusted join accounts as High Value in order to exclude them from the analysis.

Then, run the following Raw Query to show all the ACLs from users to computers, which would result in a similar graph as the first screenshot in case computers were joined by regular user accounts:

MATCH p = (u:User)-[r]->(c:Computer) WHERE u.highvalue = false AND r.isacl = true RETURN p

Conclusion

Joining computers is not a task that you want to trust everyone with, since the joiner account can obtain administrative privileges on the joined computer. The recommended way to join computers is to have a dedicated account for this task.

In this post, we’ve seen the power of accounts joining computers to the domain and the importance to protect them. We’ve also observed that, as for many other points, it is important to harden the configuration of your Active Directory, since it is not shipped with a restrictive configuration by default.

References

Microsoft references about joining computers:

Several good explanations about delegation: