# CreateComputer

## Summary

|                            |                                      |
| -------------------------- | ------------------------------------ |
| **FSProtect ACL Alias**    | CreateComputer                       |
| **AD Alias**               | Create computer objects              |
| **Affected Object Types**  | OUs, Domains, Containers             |
| **Exploitation Certainty** | Certain                              |
| **AD Right**               | CreateChild                          |
| **AD Class**               | Computer                             |
| **AD Class Guid**          | bf967a86-0de6-11d0-a285-00aa003049e2 |

## Description

The `CreateComputer` permission in Active Directory allows you to create new computer accounts. This is useful when you need to quickly add new devices to the network, such as servers or office computers, and ensure they can access appropriate services. When set up correctly, it helps administrators do their work more efficiently and maintains smooth network operations.

However, if this permission is not managed properly, it can create security risks. If an attacker gains this permission, they could create fake computer accounts, hide their activities, and gain access to sensitive parts of the network. This could lead to stolen data, unauthorized changes, and long-lasting, difficult-to-detect security threats. Therefore, it is important to carefully control who can use the `CreateComputer` permission.

## Identification

### PowerShell

#### Active Directory Module

Using the ActiveDirectory PowerShell module, you can enumerate `CreateComputer` entries.

**1.** Find-CreateComputer function

```powershell
function Find-CreateComputer {
    [CmdletBinding()]
    param ( [string]$Target = $null,[string]$SearchBase = $null, [string]$OutputPath = "CreateComputer.csv",[switch]$ExcludeAdmins = $false)
    Import-Module ActiveDirectory

    Write-Host "Gathering Active Directory OUs/Containers and inspecting ACLs for explicit 'CreateChild' permissions on the 'Computer' class..."
    # Access Control Type of Access Control Entry (Allow)
    $AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow;
    # Active Directory Rights of Access Control Entry (CreateChild)
    $ActiveDirectoryRights = [System.DirectoryServices.ActiveDirectoryRights]::CreateChild;
    # https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adsc/142185a8-2e23-4628-b002-cf31d57bb37a
    $ComputerClassGuid = "bf967a86-0de6-11d0-a285-00aa003049e2";
    $ExcludedSIDs = @()
    if ($ExcludeAdmins) {
        Write-Host "Excluding default administrative groups and built-in accounts."
        $ExcludedSIDs += (New-Object System.Security.Principal.NTAccount "NT AUTHORITY\SYSTEM").Translate([System.Security.Principal.SecurityIdentifier]),(New-Object System.Security.Principal.NTAccount "NT AUTHORITY\SELF").Translate([System.Security.Principal.SecurityIdentifier]),(New-Object System.Security.Principal.NTAccount "BUILTIN\Account Operators").Translate([System.Security.Principal.SecurityIdentifier]),(New-Object System.Security.Principal.NTAccount "BUILTIN\Administrators").Translate([System.Security.Principal.SecurityIdentifier]),(New-Object System.Security.Principal.NTAccount "NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS").Translate([System.Security.Principal.SecurityIdentifier])
        try {
            $ExcludedSIDs += (Get-ADGroup -Identity "Domain Admins").SID;$ExcludedSIDs += (Get-ADGroup -Identity "Enterprise Admins").SID
            $ExcludedSIDs += (Get-ADGroup -Identity "Schema Admins").SID;$ExcludedSIDs += (Get-ADGroup -Identity "Cert Publishers").SID
            $ExcludedSIDs += (Get-ADGroup -Identity "Group Policy Creator Owners").SID;$ExcludedSIDs += (Get-ADGroup -Identity "Domain Controllers").SID
            $ExcludedSIDs += (Get-ADGroup -Identity "Key Admins").SID;$ExcludedSIDs += (Get-ADGroup -Identity "Enterprise Key Admins").SID
            $ExcludedSIDs += (Get-ADGroup -Identity "DnsAdmins").SID; $ExcludedSIDs += (Get-ADGroup -Identity "RAS and IAS Servers").SID
        }
        catch {
            Write-Warning "Could not resolve one or more default domain admin groups (e.g., Domain Admins, Enterprise Admins, Schema Admins). They might not be filtered from results."
        }
    }
    $foundAcls = @()
    $objectsToScan = @()

    try {
        if ($Target) {
            Write-Host "Searching for permissions on specific object: '$Target'."
            $specificObject = Get-ADObject -Identity $Target -Properties nTSecurityDescriptor -ErrorAction Stop
            if ($specificObject) {
                $objectsToScan += $specificObject
            } else {
                Write-Output "Object '$Target' not found."
                return
            }
        } else {
            $adObjectParams = @{
                Filter    = "ObjectClass -eq 'organizationalUnit' -or ObjectClass -eq 'container'"
                Properties = "nTSecurityDescriptor"
                ErrorAction = "Stop"
            }
            if ($SearchBase) {
                $adObjectParams.Add("SearchBase", $SearchBase)
                Write-Host "Searching for OUs and containers within '$SearchBase'."
            } else {
                Write-Host "Searching for all OUs and containers in the domain."
            }
            $objectsToScan = Get-ADObject @adObjectParams
        }
        if (-not $objectsToScan) {
            Write-Output "No Active Directory Organizational Units or Containers found matching the criteria."
            return
        }
        foreach ($obj in $objectsToScan) {
            $ObjectDistinguishedName = $obj.DistinguishedName;
            try {
                $acl = Get-Acl -Path "AD:$ObjectDistinguishedName"
                foreach ($ace in $acl.Access) {
                    $isExcluded = $false
                    if ($ExcludeAdmins) {
                        try {
                            if ($ExcludedSIDs -contains $ace.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier])) {
                                $isExcluded = $true;
                            }
                        }
                        catch {
                            Write-Warning "Could not translate SID for exclusion check: $($ace.IdentityReference.Value). Error: $($_.Exception.Message)"
                        }
                    }
                    if ($ace.AccessControlType -eq $AccessControlType -and
                        ($ace.ActiveDirectoryRights -band $ActiveDirectoryRights) -and # Use -band for bitwise comparison
                        ($ace.ObjectType -eq $ComputerClassGuid) -and
                        -not $ace.IsInherited -and
                        -not $isExcluded) { # Apply exclusion filter

                        # Add the found entry to the results array
                        $foundAcls += [PSCustomObject]@{
                            'Vulnerable Container' = $ObjectDistinguishedName
                            'Internal Threat'      = $ace.IdentityReference.Value # Get the string representation
                        }
                    }
                }
            }
            catch {
                Write-Warning "Could not retrieve ACL for '$ObjectDistinguishedName': $($_.Exception.Message)"
            }
        }
    }
    catch {
        Write-Error "Failed to retrieve Active Directory Organizational Units or Containers: $($_.Exception.Message)"
        return
    }
    if ($foundAcls.Count -gt 0) {
        $exclusionMessage = if ($ExcludeAdmins) { " (excluding default admin groups and built-in accounts)" } else { "" }
        Write-Host "Found $($foundAcls.Count) Active Directory container(s) with explicit 'CreateChild' permissions on the 'Computer' class$exclusionMessage."
        try {
            # Filter out duplicate entries before exporting based on both columns
            $foundAcls | Sort-Object -Unique 'Vulnerable Container', 'Internal Threat' | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
            Write-Output "Results exported successfully to '$OutputPath'"
        }
        catch {
            Write-Error "Failed to export results to CSV file '$OutputPath': $($_.Exception.Message)"
        }
    } else {
        $exclusionMessage = if ($ExcludeAdmins) { " (excluding default admin groups and built-in accounts)" } else { "" }
        Write-Output "No Active Directory container(s) found with explicit 'CreateChild' permissions on the 'Computer' class$exclusionMessage."
    }
}
```

**2.** Scan all Objects

```powershell
Find-CreateComputer
```

**3.** Scan a specific object

```powershell
Find-CreateComputer -Target "OU=Workstations,DC=forestall,DC=labs" 
```

**4.** To exclude default admin ACLs to improve visibility

```powershell
Find-CreateComputer -ExcludeAdmins
```

#### .NET Directory Services

By leveraging PowerShell’s built-in .NET DirectoryServices namespace, you can enumerate `CreateComputer` entries without relying on any external modules or dependencies.

**1.** Find-CreateComputerSimple function

```powershell
function Find-CreateComputerSimple {
    [CmdletBinding()]
    param ([string]$Target = $null, [string]$OutputPath = "CreateComputer.csv",[switch]$ExcludeAdmins = $false)
    $createChildRight = [System.DirectoryServices.ActiveDirectoryRights]::CreateChild
    $allow = [System.Security.AccessControl.AccessControlType]::Allow
    $computerClassGuid = [Guid]"bf967a86-0de6-11d0-a285-00aa003049e2"
    if ($ExcludeAdmins) {
        Write-Host "Resolving well-known SIDs to exclude..."
        $ExcludedSIDs = @(
            "NT AUTHORITY\SYSTEM","NT AUTHORITY\SELF","BUILTIN\Account Operators","BUILTIN\Administrators",
            "NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS","Domain Admins","Enterprise Admins", "Schema Admins", "Cert Publishers",
            "Group Policy Creator Owners","Domain Controllers", "Key Admins", "Enterprise Key Admins", "DnsAdmins", "RAS and IAS Servers"
        ) | ForEach-Object {
            try {
                (New-Object System.Security.Principal.NTAccount $_).Translate([System.Security.Principal.SecurityIdentifier])
            } catch {
                Write-Warning "Failed to resolve SID for $_"
            }
        }
    }
    $containers = @()
    if ($Target) {
        Write-Verbose "Binding to $Target..."
        try {
            $containers += New-Object System.DirectoryServices.DirectoryEntry("LDAP://$Target")
        } catch {
            Write-Error "Failed to bind to '$Target': $_"
            return
        }
    }
    else {
        Write-Verbose "Binding to RootDSE to find all OUs and Containers..."
        try {
            $root     = New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
            $baseDN   = $root.Properties["defaultNamingContext"][0]
            $searcher = New-Object System.DirectoryServices.DirectorySearcher("LDAP://$baseDN")
            $searcher.Filter = "(|(objectClass=organizationalUnit)(objectClass=container))"
            $searcher.PageSize = 1000
            [void]$searcher.PropertiesToLoad.Add("distinguishedName")
            $results = $searcher.FindAll()

            foreach ($res in $results) {
                try {
                    $containers += $res.GetDirectoryEntry()
                } catch {
                    Write-Warning "Could not bind container: $_"
                }
            }
        } catch {
            Write-Error "LDAP enumeration failed: $_"
            return
        }
    }
    $found = @()
    foreach ($entry in $containers) {
        $dn = $entry.distinguishedName
        Write-Verbose "Checking ACLs on: $dn"
        try {
            $acl  = $entry.ObjectSecurity
            $aces = $acl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])
        } catch {
            Write-Warning "Could not read ACL on $dn : $_"
            continue
        }
        foreach ($ace in $aces) {
            if (
                $ace.AccessControlType -eq $allow -and
                ($ace.ActiveDirectoryRights -band $createChildRight) -and
                $ace.ObjectType -eq $computerClassGuid -and
                -not $ace.IsInherited
            ) {
                if ($ExcludeAdmins -and $ExcludedSIDs -contains $ace.IdentityReference) {
                    continue
                }
                $who = try {
                    $ace.IdentityReference.Translate([System.Security.Principal.NTAccount]).Value
                } catch {
                    $ace.IdentityReference.Value
                }
                $found += [PSCustomObject]@{
                    "Vulnerable Container" = $dn.ToString();
                    "Internal Threat"      = $who
                }
            }
        }
    }
    if ($found) {
        $found | Sort-Object -Property "Vulnerable Container", "Internal Threat" -Unique | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
        Write-Host "Exported $($found.Count) entr$(if($found.Count -eq 1){'y'}else{'ies'}) to $OutputPath"
    } else {
        Write-Host "No 'CreateChild' ACEs on Computer class found."
    }
}
```

**2.** Scan all containers in the domain

```powershell
Find-CreateComputerSimple
```

**3.** Scan a specific container in the domain

```powershell
Find-CreateComputerSimple -Target "OU=Workstations,DC=forestall,DC=labs"
```

**4.** To exclude default admin ACLs to improve visibility

```powershell
Find-CreateComputerSimple -ExcludeAdmins
```

### Active Directory Users and Computers

**1.** Open `Active Directory Users and Computers` on your Windows server.

**2.** Right-click the object name.

**3.** Select `Properties` from the context menu.

**4.** In the Properties window, navigate to the `Security` tab.

**5.** Click the `Advanced` button to open the Advanced Security Settings dialog.

**6.** In the Advanced Security Settings window, locate and select the relevant Access Control Entry (ACE) for the user or group you wish to configure.

**7.** Click `Edit` to modify the selected ACE.

**8.** In the permissions list, locate and check the option `Create computer objects`.

**9.** Click `OK` to save your changes and close all dialogs.

![Active Directory Users and Computers](/files/xYOcUH27om297Rd0KNCG)

## Exploitation

### Windows

```powershell
New-ADComputer -Name "<Name of new computer>" -Path "<Path of vulnerable Object>"
```

Example:

```powershell
New-ADComputer -Name "VM05" -Path "OU=Workstations,DC=forestall,DC=labs"
```

To change the password of the computer object:

```powershell
$pw = ConvertTo-SecureString '<pass>' -AsPlainText -Force
Set-ADAccountPassword -Identity '<computerName>$' -NewPassword $pw
```

Example:

```powershell
$pw = ConvertTo-SecureString 'P@ssw0rd123!' -AsPlainText -Force
Set-ADAccountPassword -Identity 'VM05$' -NewPassword $pw
```

![create computer using powershell](/files/4VNNYUxXiiN5BVst1WJh)

### Linux

```bash
impacket-addcomputer -computer-name '<newcomputername>' -computer-pass '<computerpass>'  -dc-host '<DCIP>'  '<domain>'/'<user>':'<pass>'
```

Example:

```bash
impacket-addcomputer -computer-name 'vm05' -computer-pass 'Temp123!'  -dc-host '192.168.100.100'  'FORESTALL.LABS'/'ADAM':'Temp123!'
```

![create computer using impacket](/files/Wh1ZBeOacpIFV4NgTsPm)

## Mitigation

Dangerous Access Control Entries should be removed by following the steps below.

**1.** Open `Active Directory Users and Computers`, and enable the `Advanced Features` option.

**2.** Double-click the affected object and open the `Security` tab.

**3.** In this tab, click the `Advanced` button and open the suspicious Access Control Entry.

**4.** Remove the rights identified as dangerous.

**5.** Click `OK` and `Apply` to save the changes.

![active Directory Users and Computers](/files/xYOcUH27om297Rd0KNCG)

## Detection

Adding new Access Control Entries to Active Directory objects modifies the `ntSecurityDescriptor` attribute of those objects These changes can be detected with Event IDs 5136 and 4662 to identify suspicious modifications.

| Event ID | Category                                            | Description                              | Fields/Attributes                                                                                                              | References                                                                                 |
| -------- | --------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| 5136     | Audit Directory Service Changes                     | A directory service object was modified. | ntSecurityDescriptor                                                                                                           | <https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5136> |
| 4662     | Audit Directory Service Access                      | An operation was performed on an object. | AccessList, AccessMask                                                                                                         | <https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662> |
| 4724     | An attempt was made to reset an account's password. | Subject, TargetAccount                   | <https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4724> |                                                                                            |
| 4722     | A user account was enabled.                         | Subject, TargetAccount                   | <https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4722> |                                                                                            |

## References

* [c-computer Class - Microsoft Docs](https://learn.microsoft.com/en-us/windows/win32/adschema/c-computer)
* [AD Computer Objects: Properties & Management - Windows Active Directory](https://www.windows-active-directory.com/ad-computer-objects-properties-management.html)
* [Create Computer Objects - ManageEngine](https://www.manageengine.com/products/ad-manager/help/user_management/bulk-computer-modification/create-computer-objects.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestall.io/fsprotect/edges/ad/createcomputer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
