MachineAccountQuota (MAQ) is a domain level attribute that by default permits unprivileged users to attach up to 10 computers to an Active Directory (AD) domain. My first run-in with MAQ was way back in my days as a network administrator on a new job. I was assigned the task of joining a remote location’s systems to AD. After adding 10, I received this message on my next attempt:

Maqerror

Researching the error message lead me to ms-DS-MachineAccountQuota. The details lined up with the unprivileged AD access I had been provided. I reached out to a fellow admin and explained the situation. He wasn’t familiar with how to increase the quota for my account. Instead, he provided me with a domain admin account to continuing working (privesc!).

Powermad

In late 2017, I released Powermad, which is a collection of PowerShell functions derived from an LDAP domain join packet capture. After digging through the packets, I identified the single encrypted LDAP add that created the machine account object. Here is an example of the LDAP add in an unencrypted state:

Maqldapadd

My main motivation while developing Powermad was to more easily incorporate MAQ during testing. In the past, I had seen testers leverage MAQ by attaching a full Windows OS to a domain. Rather than only using MAQ in this way, I wanted to be able to just add a machine account (aka computer account) set with a known password.

Maqnew

So Is MachineAccountQuota Useful?

Since I first started working on Powermad, I’ve learned a lot about MAQ beyond just the default 10 system limit. Recently, I’ve learned even more from some amazing blog posts by Elad Shamir, Harmj0y, and Dirk-jan, in which MAQ makes an appearance.

Overall, the conclusion I’ve reached is that MachineAccountQuota is useful…

Sciencemaq

…sometimes.

In this blog post, I’ll go through 10 rules for working with MAQ as an attacker. I wrote these rules from the perspective of just adding a machine account to AD rather than attaching a Windows OS. Later, I’ll apply some of the rules to a MAQ + Kerberos unconstrained delegation use case. Finally, I’ll address defending against MAQ related exploits (spoiler: set to 0).

What Are The Rules?

I’ve broken up what I know about MAQ into 10 rules. Hopefully, you can use these rules to determine if MAQ can be useful in any particular situation.

  1. MAQ allows unprivileged users to add machine account objects to a domain. By default, an unprivileged user can create 10 machine accounts.

    Maqdefault

    You do not need to do anything special to invoke MAQ. You can simply attempt to add a machine account using an account that has not been directly granted the domain join privilege.
  2. The creator account’s SID is stored in the machine account’s ms-DS-CreatorSID attribute. AD populates this attribute only when the creator is not an administrator, or has not been delegated the privilege to add machine accounts.

    Maqcreatorsid

    AD also uses ms-DS-CreatorSID to calculate the current count against MAQ. From a testing perspective, keep in mind the attribute is an arrow pointing to the creator account, even with nested MAQ usage. Therefore, using machine accounts created through MAQ does not fully shield the creator account.

    Maqcreatorsid

    If the defense is aware of the ms-DS-CreatorSID attribute though, there is probably a good chance they have already disabled MAQ.
  3. Machine accounts created through MAQ are placed into the Domain Computers group. In situations where the Domain Computers group has been granted extra privilege, it’s important to remember that this privilege also extends to unprivileged users through MAQ. For example, you may find Domain Computers listed within a local Administrators group.

    Maqlocaladmin

    Or even better, within a Domain Administrators group.

    Maqda

    As a slight extension to this rule, be on the lookout for automation that places computers in OUs and/or groups based on portions of the machine account name. You may be able to leverage the automation through MAQ.
  4. The creator account is granted write access to some machine account object attributes. Normally, this includes the following attributes:
    1. AccountDisabled
    2. description
    3. displayName
    4. DnsHostName
    5. ServicePrincipalName
    6. userParameters
    7. userAccountControl
    8. msDS-AdditionalDnsHostName
    9. msDS-AllowedToActOnBehalfOfOtherIdentity
    10. samAccountName

      You can modify these attributes as needed.
      Maqwrite
      However, the permitted values of some attributes are still subject to validation.

  5. The machine account itself has write access to some of its own attributes. The list includes the msDS-SupportedEncryptionTypes attribute which can have an impact on the negotiated Kerberos encryption method. Modern Windows OS builds will set this attribute to 28 during the process of joining a domain.Maqself
  6. The attribute validation is strict at the time the machine account is added. Basically, the attribute values need to match up. If they don’t match, the add will fail such as in this example where the samAccountName is incorrect.
    Maqldapadd
    Strangely, after a machine account is added, some of the validation rules are relaxed.
  7. The samAccountName can be changed to anything that doesn’t match a samAccountName already present in a domain. Changing this attribute can be helpful for blending in activities with legitimate traffic such as by stripping the ‘$’ character or by matching an in-use account naming convention. Interestingly, the samAccountName can even end in a space which permits mimicking any existing domain account.
    Maqsamaccoutnname
    Here is how the fake ‘Administrator’ account appears in action.
    Maqsamaccountname
    Note, changing the samAccountName will not change the actual machine account object name. Therefore, you can have a machine account object that blends in with the naming convention while also having a completely different samAccountName.
  8. Adding a machine account creates 4 SPNs. The list includes the following:
    1. HOST/MachineAccountName
    2. HOST/MachineAccountName.domain.name
    3. RestrictedKrbHost/MachineAccountName
    4. RestrictedKrbhost/MachineAccountName.domain.name

      As an example, here is the default SPN list for the ‘test.inveigh.net’ machine account.
      Maqspn
      After you add the machine account, you can append or replace the list with any SPN that passes validation.
      Maqspn

      If you modify the samAccountName, DnsHostname, or msDS-AdditionalDnsHostName attributes, the SPN list will automatically update with the new values. The default SPNs do cover a lot of use cases though. So, you won’t always need to modify the list. If more information on SPNs is needed, Sean Metcalf has really good list at AdSecurity which includes details on Host and RestrictedKrbHost.

  9. Machine accounts do not have logon locally privilege. However, machine accounts work just fine from the command line with tools that accept credentials directly or through ‘runas /netlonly’. The tasks can include enumeration, adding DNS records, or really just about any non-GUI action that applies to a user account.Maqrunas
  10. Machine accounts added through MAQ cannot be deleted by the unprivileged creator account. To completely cleanup AD after using MAQ, you will need to elevate domain privilege or pass the task along to your client. You can however disable the account with the unprivileged creator account.Maqdisable

MachineAccountQuota In Action

Let’s take the above rules and apply them to a compromised AD account that has SeEnableDelegationPrivilege. As mentioned in rule 4, even though an account has write access to an attribute, the write attempt is still subject to validation.

Maqdelegation

However, if you happen to compromise an account with the correct privilege, such as SeEnableDelegationPrivilege, things can get interesting.

Maqdelegation

In this case, we can use the ‘INVEIGHkevin’ account, along with MAQ, to create and configure a machine account object capable of performing Kerberos unconstrained delegation. Conveniently, this can remove the requirement for finding an existing suitable AD object for leveraging SeEnableDelegationPrivilege. Basically, we can just make our own through MAQ.

Note, this is one of those scenarios where, if you can, just joining a domain with your own Windows system can make things easier. If you do go that route, just enable unconstrained delegation on the machine account object and leverage it just like you would on a compromised system. The good news is that the process is still very manageable when we use only a machine account.

Kerberos Unconstrained Delegation Setup

For this scenario, let’s assume that we have unprivileged access on a random Windows domain system and have also compromised an SeEnableDelegationPrivilege account.

Here are the steps to setup the attack:

  1. Use the SeEnableDelegationPrivilege account to add a machine account through MAQ.Maqldapadd
  2. Enable unconstrained delegation by setting the userAccountControl attribute to 528384.Maqdelegation
  3. Optionally, set the msDS-SupportedEncryptionTypes attribute to set the desired Kerberos encryption type using the machine account’s credentials.Maqencryption
  4. Optionally, add a corresponding DNS record matching the SPNs and pointing to the compromised Windows system. This can usually be done with through either dynamic updates or LDAP. This is optional since with the default SPNs, Kerberos will can also trigger from other name resolution methods such as LLMNR/NBNS.Maqadidns

Kerberos Unconstrained Delegation Attack

With the above in place, we next need to sort out how to get the desired account traffic to the compromised host. For this first round, we’ll use tifkin’s printer bug to get a domain controller machine account to connect to our system over SMB. Additionally, we will be using the dev Branch version of Inveigh. Through packet sniffing, this version can grab SMB Kerberos TGT traffic and attempt to output a kirbi file for use with tools such as Mimikatz and Rubeus.

For Inveigh, we will need to have either the unconstrained delegation account’s AES256 hash or a PSCredential object with a Kerberos salt as the username. Shown below is the process of generating the correct AES256 hash using Powermad’s Get-KerberosAESKey function.

Maqaeshash

Note, Inveigh currently only supports AES256 Kerberos decryption.

Since we want to use our unconstrained delegation machine account’s SPN, we will need to have the target connect to the correct host name. For this example, I’ll use Dirk-jan‘s printerbug script from his recently released Krbrelayx toolkit.

Maqprinterbug

At this point, let’s take a step back and go over the various SPNs in play. First, we have a compromised system running an SMB server as SYSTEM. This means that the SMB server will decrypt Kerberos tickets using the system’s machine account credentials. If we cause an SPN mismatch and attempt to perform Kerberos authentication with data encrypted under a different SPN, the SMB authentication will fail. However, the SMB server will not reject the authentication attempt until after the client has transmitted the AP-REQ.

Maqsmb

More importantly for this scenario, the SMB server will reject the connection after receiving the TGT. Therefore, if we can grab the Kerberos traffic through packet sniffing, we can decrypt the needed data with the machine account credentials we have in our possession.

Maqinveigh

Note, using the SPN mismatch trick has a tendency to trigger multiple Kerberos authentication attempts from a client. I have Inveigh set to only output 2 kirbi files per user by default. Inveigh stores the rest in memory for access through Get-Inveigh.

Now that we have a kirbi TGT for the domain controller, we can pass it to Mimikatz and attempt a dcsync.

Maqmimikatz

For another quick example, I used Inveigh to capture a Domain Administrator TGT over SMB.

Maqkirbi

Next, I used the kirbi file with Rubeus.

Maqrubeus

As a last example, below is Inveigh catching a TGT over HTTP.

Maqinveighhttp

HTTP may, in ideal conditions, remove the requirement for local administrator access on the compromised system.

Finally, the Kerberos unconstrained delegation technique above would also work well with the new krbrelayx toolkit.

One last word on SeEnableDelegationPrivilege + MAQ, fully setting up standard constrained delegation is usually out of reach due to the lack of write access to msDS-AllowedToDelegateTo.

Defending Against MachineAccountQuota

I believe that MAQ is just one of those default settings without enough awareness. I’m guessing companies rarely actually need the default MAQ setting or even need it enabled at all. To disable MAQ simply set the count to 0. If you do need to allow unprivileged users to add systems, the better route is to just delegate the privilege to specific groups. Just be aware that much of what is listed in this blog post would also apply to a compromised account with delegated domain join privilege.

Defenders can also keep an eye out for two things:

  • Populated ms-DS-CreatorSID attributes
  • Machine accounts that are not changing their passwords

Conclusion

As with most things, MachineAccountQuota usage is situational. For testers, it is however something that is worthy of consideration for your bag of tricks. This has become even more apparent with recently released techniques from researchers such as Elad Shamir. For defenders, I recommend just disabling MachineAccountQuota.

Special thanks to Karl Fosaaen for the Always Sunny photoshop.