# ContainerWrite

### Summary

|                            |                |
| -------------------------- | -------------- |
| **FSProtect ACL Alias**    | ContainerWrite |
| **AD Alias**               | GpoCustom      |
| **Affected Object Types**  | Group Policies |
| **Exploitation Certainty** | Certain        |

### Description

The `ContainerWrite` Permission in Active Directory grants a user `GpoCustom` access, enabling them to modify and manage Group Policy Objects directly. When properly assigned, this permission allows authorized administrators to create, configure, and update policies that control user environments and system behaviors across the domain. With `ContainerWrite`, administrators can define security settings, deploy software, configure system preferences, and implement organizational policies in a centralized manner.

However, if granted inappropriately, the `ContainerWrite` permission poses significant security risks. An attacker or unauthorized user with `ContainerWrite` access could alter critical security settings, disable protective measures, or implement harmful configurations affecting all linked computers and users. Since Group Policy settings often apply to entire organizational units or domains, this permission effectively enables wide-reaching changes across the network environment. Additionally, attackers could embed malicious commands or code in these configurations. Because such scripts may run with elevated privileges (e.g., Domain Admins), any harmful modifications can rapidly compromise the network.

### Identification

You can identify `ContainerWrite` on domain with this script

```powershell
# Importing ActiveDirectory Module
Import-Module ActiveDirectory
Import-Module GroupPolicy

# Access Control Type of Access Control Entry (Allow or Deny)
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow;

# Active Directory Rights of Access Control Entry
$ActiveDirectoryRights = "WriteProperty";
$ActiveDirectoryRights2 = "GenericAll";
$ActiveDirectoryRights3 = "GenericWrite";
$ContainerWritePermissionGuid = "00000000-0000-0000-0000-000000000000";

# Iterating all GPOs
 Get-GPO -All |

ForEach-Object {
    
    # Extracting Path
    $GPOPath = $_.Path;
    $DisplayName = $_.DisplayName
    # Retrieving Access Control Entries of GPO
    (Get-Acl -Path "AD:$GPOPath").Access |

    # Filtering Non-Inherited Allowed ACEs
    Where-Object {
        $_.AccessControlType -eq $AccessControlType -and
        $_.ActiveDirectoryRights -like "*$ActiveDirectoryRights*" -or
        $_.ActiveDirectoryRights -like "*$ActiveDirectoryRights2*" -or
        $_.ActiveDirectoryRights -like "*$ActiveDirectoryRights3*" -and
        $_.ObjectType -eq $ContainerWritePermissionGuid -and
        $_.IsInherited -eq $false
        
    } | 
    
    # Selecting GPO's Name and ACE Holder
    Select-Object @{Name="Vulnerable GPO";Expression={$DisplayName}}, 
                  @{Name="Internal Threat";Expression={$_.IdentityReference}},
                  @{Name="Permissions";Expression={$_.ActiveDirectoryRights}}
} | 

# Exporting found Access Control Entries into CSV file
Export-Csv -Path "ContainerWrite.csv" -NoTypeInformation
```

Above mentioned code is scans all GPOs in the domain. You can scan specify GPO by changing `GPOName` Variable in the code mentioned below

```powershell
# Importing ActiveDirectory and GroupPolicy modules
Import-Module ActiveDirectory
Import-Module GroupPolicy


$GPOName = 'DC_GPO'


# Access Control Type of Access Control Entry (Allow or Deny)
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow;

# Active Directory Rights of Access Control Entry
$ActiveDirectoryRights = "WriteProperty";
$ActiveDirectoryRights2 = "GenericAll";
$ActiveDirectoryRights3 = "GenericWrite";
$ContainerWritePermissionGuid = "00000000-0000-0000-0000-000000000000";

$GPO = Get-GPO -Name $GPOName

$GPOPath = $GPO.Path

# Retrieving Access Control Entries of GPO
(Get-Acl -Path "AD:$GPOPath").Access |


# Filtering Non-Inherited Allowed GenericWrite Permission
Where-Object {
    $_.AccessControlType -eq $AccessControlType -and
    $_.ActiveDirectoryRights -like "*$ActiveDirectoryRights*" -or
    $_.ActiveDirectoryRights -like "*$ActiveDirectoryRights2*" -or
    $_.ActiveDirectoryRights -like "*$ActiveDirectoryRights3*" -and
    $_.ObjectType -eq $ContainerWritePermissionGuid -and
    $_.IsInherited -eq $false       
} | 

    # Selecting GPO's Name and ACE Holder
Select-Object @{Name="Vulnerable GPO";Expression={$GPO.DisplayName}}, 
    @{Name="Internal Threat";Expression={$_.IdentityReference}},
    @{Name="Permissions";Expression={$_.ActiveDirectoryRights}} | 

# Exporting found Access Control Entries into CSV file
Export-Csv -Path "ContainerWrite.csv" -NoTypeInformation
```

To identify `ContainerWrite` using `Group Policy Management`, follow the steps below:

**1.** Open `Group Policy Management`.

**2.** Find and click on the Group Policy.

**3.** Select Delegation from the context menu then click Advanced.

**4.** Click on the Advanced button to open the Advanced Security Settings dialog in GPO's security settins window.

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

**6.** Click Edit to modify the selected ACE.

**7.** In the permissions list, locate and check the dangerous options (like `WriteProperty`, `GenericWrite` or \`GenericAll ) .

**8.** Click OK to save your changes and close the dialogs.

<figure><img src="/files/iepXRTLpJLMGqwczibkq" alt=""><figcaption></figcaption></figure>

### Exploitation

This permission can be can be exploitable on Windows systems

The Logon scripts automatically executes a specific script during the user login process. This setting triggers the script to run as part of the login sequence. For adding Logon script follow steps below

**1.** Open `Group Policy Management`.

**2.** Find and right-click on the Group Policy.

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

**4.** Follow this location with expanding policies `User Configuration > Policies > Windows Settings > Scripts (Logon/Logoff) in` Group Policy Management Editor\`\`

**5.** Double-click `Logon`

**6.** Click `Add...` then click browse or write path of the script

**7.** Write Parameters of script and click OK

**8.** Click Apply to save your changes and close the dialogs.

<figure><img src="/files/i44lmSDhWTJngvKMziwt" alt=""><figcaption></figcaption></figure>

#### *Important Note*

If this logon/logoff script affects authorized users (for example, the default domain policy affects authenticated users, which includes administrators and other authorized users), then when an authorized user logs in or logs off, the script will run with the high privilege.

### Mitigation

Access Control Entries identified as dangerous should be removed by following the steps below.

**1.** Open `Group Policy Management`.

**2.** Find and click on the Group Policy.

**3.** Select Delegation from the context menu then click Advanced.

**4.** Click on the Advanced button to open the Advanced Security Settings dialog in GPO's security settins window.

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

**6.** Click Edit to modify the selected ACE.

**7.** In the permissions list, locate and remove the dangerous options (like `WriteProperty`, `GenericWrite` or \`GenericAll ) .

**8.** Click OK to save your changes and close the dialogs.

<figure><img src="/files/K9ofGbFpBwYX2tD5wiVm" alt=""><figcaption></figcaption></figure>

### Detection

Adding new Access Control Entries on the Active Directory objects changes the `ntSecurityDescriptor` attribute of the objects themselves. These changes can be detected with the 5136 and 4662 Event ID's to identify dangerous modifications.

| Event ID | Description                              | Fields/Attributes      | References                                                                                 |
| -------- | ---------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------ |
| 5136     | A directory service object was modified. | ntSecurityDescriptor   | <https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5136> |
| 4662     | An operation was performed on an object. | AccessList, AccessMask | <https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662> |

### References

{% embed url="<https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn789190(v=ws.11)>" %}
MicrosoftLearn
{% endembed %}

{% embed url="<https://support.keriocontrol.gfi.com/hc/en-us/articles/360015180040-Configuring-Login-Logout-scripts-via-GPO>" %}
support.keriocontrol.gfi.com
{% endembed %}


---

# 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/containerwrite.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.
