Select Page

While the title to this post may sound a bit scary or ominous, the subject of this post is definitely real. A fellow IT guy whom I’ve known for many years, alerted me to a situation he came across in an IT shop he was helping. Namely, the customer’s computers got infected with a ransomware virus, which as you may know, is designed to encrypt hard drives–forcing the owner to pay a ransom to get the decryption key (hopefully) and regain access to their data. Most troubling, ransomware authors are now finding ways to encrypt whole organizations’ computers–delivering their malware effectively to all machines on a network using a variety of means.

Group Policy-Based Malware Delivery

This is where Group Policy enters the equation. My friend found out that the crypto-malware managed to create a Group Policy Preferences Scheduled Task policy within the Default Domain Policy (!) that delivered a PowerShell script that executed on all machines to install the malware. To say I was shocked by this would be an understatement and it represents, to me anyway, that malware authors are getting increasingly clever about using loose enterprise IT management practices around Active Directory (AD) and Group Policy to use the infrastructure against itself. This follows on from my observations from last Summer’s Black Hat conference about how hacker tools are starting to use information that is generally available within AD and GP environments, to improve their ability to perform lateral movement and pass-the-hash style attacks. In that article, I talked about setting permissions on GPOs that contained per-computer security policy–and that they should be permissioned so that general user accounts in the domain cannot READ those GPOs.  In this case, we have over-generous WRITE permissions resulting in a GPO being used as a vector for malware distribution.

So, how did this particular malware write to the Default Domain Policy? Simple. This customer environment had a large number of user accounts that had write permissions on the DDP. All it took was compromising one of those user’s machines to give the malware the ability to write to the DDP, which, being linked at the domain level and processed by all computers and users by default, is a perfect built-in domain-wide delivery vehicle that exists in every AD domain across the planet, has a well-known name and GUID and frankly, should never, ever be widely writeable. By default, GPOs grant edit permissions to Domain Admins, Enterprise Admins and System, as shown below, but you can alter this using GPMC or the Group Policy PowerShell module:

Viewing the Default Permissions on a GPO

Viewing the Default Permissions on a GPO

Protecting Yourself

So, what should you do to prevent this sort of thing from happening in your environment? Well the first step is to make sure you don’t have the same problem as this customer. Specifically, make sure that any domain-level-linked GPOs you have are suitably locked down for delegation. I’ve written a PowerShell script (below) that specifically looks for domain-linked GPOs, enumerates the permissions on them and lists out the users (through direct or indirect AD group membership) that have some level of edit permissions on those GPOs.

 
function Get-GPOWritePermissions
{
    
    Param
    (
        # OU takes a DN to query GPO links on. Default is the domain

        $OU = (Get-ADDomain).DistinguishedName
    )
    import-module -Name grouppolicy
    import-module -Name ActiveDirectory
    $DomainLinkedGPOs = (Get-GPInheritance -Target $OU).GpoLinks
    foreach ($gpo in $DomainLinkedGPOs)
    {
        $userList = @{}
        $perms = Get-GPPermission -Name $gpo.DisplayName -all
        foreach ($ace in $perms)
        {
            if ($ace.Trustee.Name -eq "SYSTEM")
                {continue}

            if ($ace.Permission -eq [Microsoft.GroupPolicy.GPPermissionType]::GpoEditDeleteModifySecurity -or $ace.Permission -eq [Microsoft.GroupPolicy.GPPermissionType]::GpoEdit)
            {
                if ($ace.Trustee.SidType -eq "Group" -or $ace.Trustee.SidType -eq "WellKnownGroup") #it's a group so enumerate its members
                {
                    (Get-ADGroupMember -Identity $ace.Trustee.Name -Recursive -ErrorAction Continue) | ForEach-Object {if (!$userList.ContainsKey($_.distinguishedName)){$userList.Add($_.distinguishedName,$_.Name)}}

                }
                else #its a single principal (e.g. user or computer) so just increment our count
                {
                    if (!$userList.ContainsKey($ace.Trustee.DSPath))
                    {
                        $userList.add($ace.Trustee.DSPath,$ace.Trustee.Name);
                    }
                }
            }
        }
        if ($userList.Count -gt 0)
        {
            "`n"
            $gpo.DisplayName + " has the following users with write permissions:"
            $userList
        }
    }
}
Get-GPOWritePermissions

This script is pretty quick and dirty–but does the job. If I spent more time on it, I would write the results to the pipeline as a custom object. The thing to note about this script is that it is only returning information on GPOs linked at the domain level, but you can use the OU parameter to feed it the DN of another container. The domain level is certainly the riskiest place to worry about, because domain-linked GPOs have the potential to apply to every user or computer. But you can imagine more crafty malware authors being intelligent about using lower-level linked GPOs in the future, so its prudent to ensure that only the smallest number of admins possible have edit rights on ALL of your GPOs. See my previous posts for a review on how Group Policy delegation works and how you can modify the default permissions on newly created GPOs. If you are following least privilege best practices, then only secondary admin accounts (i.e. not a user’s primary id) should be in privileged groups that allow GPO editing and those admin accounts should be highly restricted as to where they can logon–e.g. using Privileged Access Workstations (PAWs) or other “jump boxes”. This is just best practice in general and especially in this example, as it limits the chances that admin credentials get compromised in an attack.

 

The bottom line is, HARDEN YOUR GPOs PEOPLE! It’s no longer ok to just assume the default permissions are fine.

Darren