Powershell#
Sometimes, you need to enumerate AD on a AD joined windows computer, or you want to “living off the land”.
You need ActiveDirectory powershell module installed on the machine. Typically, this is already installed for you on most AD joined machine
Query objects#
The ActiveDirectory powershell module gives you some cmdlet to enumerate AD. Typically, those are what you want to use:
Get-ADUserGet-ADGroupGet-ADComputerGet-ADObject
With Get-ADObject, you might need to use -LDAPFilter to filter specifically what object you want, but you can just use Get-ADUser, Get-ADGroup, and Get-ADComputer to save yourself having to remember the ldap query.
For example, this is how you query all properties of all users:
# Get-ADObject
Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user))' -Properties *
# Get-ADUser
Get-ADUser -Filter * -Properties *Groups:
# Get-ADObject
Get-ADObject -LDAPFilter '(objectClass=group)' -Properties *
# Get-ADGroup
Get-ADGroup -Identity "Administrators" -Properties *And computers
# Get-ADObject
Get-ADObject -LDAPFilter '(objectCategory=computer)'
# Get-ADComputer
Get-ADComputer -Filter * -Properties *Select specific properties#
You can pipe the received objects into Select to show only specific properties:
# Get-ADObject
Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user))' -Properties * | select logonHours
# Get-ADUser
Get-ADUser -Filter * -Properties * | select logonHoursCount#
You can also count the number of objects received
# Get-ADObject
(Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user))').Count
# Get-ADUser
(Get-ADUser -Filter *).CountFilter#
You can utilize the -Filter flag to filter further things from the objects received
For example, this is how you can filter in only objects that has Name property equal to 'sally jones':
Get-ADUser -Filter "Name -eq 'sally jones'"You can also pipe it to Where for the same purpose:
Get-ADUser | Where Name -eq 'sally jones'Here’s a list of filter operators:
| Filter | Meaning |
|---|---|
| -eq | Equal to |
| -le | Less than or equal to |
| -ge | Greater than or equal to |
| -ne | Not equal to |
| -lt | Less than |
| -gt | Greater than |
| -approx | Approximately equal to |
| -bor | Bitwise OR |
| -band | Bitwise AND |
| -recursivematch | Recursive match |
| -like | Like |
| -notlike | Not like |
| -and | Boolean AND |
| -or | Boolean OR |
| -not | Boolean NOT |
SearchBase and SearchScope#
-SearchBase flag needs OU and DN like OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
-SearchScope allows us to define how deep into the OU hierarchy we would like to search:
Base- Return only the OU itself defined in-SearchBaseOneLevel- Return objects inside the OU defined in-SearchBaseSubTree- Return recursively all objects inside defined OU and nested objects
As an example, if we search for member count in an OU, with -SearchBase and no -SearchScope we got 970 users
(Get-ADUser -SearchBase "OU=Employees,DC=INLANEFREIGHT,DC=LOCAL" -Filter *).count
970When we set -SearchScope to Base, we got nothing, since it returns only the OU object itself, and no user object
(Get-ADUser -SearchBase "OU=Employees,DC=INLANEFREIGHT,DC=LOCAL" -SearchScope Base -Filter *).Count
0When we set -SearchScope to OneLevel, we got 1 user, since this is the only user directly inside the OU
(Get-ADUser -SearchBase "OU=Employees,DC=INLANEFREIGHT,DC=LOCAL" -SearchScope OneLevel -Filter *).Count
1Finally, when we set -SearchScope to SubTree, we got all 970 users, including nested users
(Get-ADUser -SearchBase "OU=Employees,DC=INLANEFREIGHT,DC=LOCAL" -SearchScope Subtree -Filter *).count
970User#
Kerberoastable users#
Get-ADUser -Properties * -filter ** | where servicePrincipalName -ne $null | Select SamAccountName,MemberOf,ServicePrincipalName | flASREP-Roastable users#
You can search for the DoesNotRequirePreAuth property, which mean that the user is vulnerable to ASREP-Roast attack
Get-ADUser -Filter {DoesNotRequirePreAuth -eq 'True'}Trusted for delegation#
A user account can be set to be trusted for delegation.
Get-ADUser -Properties * -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' | Select Name,memberof,ServicePrincipalName,TrustedForDelegation | flDescription#
Sometimes, description of a user account might have password
Get-ADUser -Properties * -LDAPFilter '(description=*)' | Select SAMAccountname,DescriptionBlank password#
Find users with useraccountcontrol attribute set with the flag PASSWD_NOTREQD meaning the account can have a blank password set
Get-AdUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=32)' -Properties * | Select Name,Memberof | flGroups of a user#
Find all group recursively that Harry Jones is a part of
Get-ADGroup -Filter 'member -RecursiveMatch "CN=Harry Jones,OU=Network Ops,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL"' | Select Name
# With ldap OID filter
Get-ADGroup -LDAPFilter '(member:1.2.840.113556.1.4.1941:=CN=Harry Jones,OU=Network Ops,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL)' | Select NameUAC attributes#
UAC attributes are not UAC windows feature.
You can enumerate user accounts and their UAC values like this. UAC value of 512 can be ignored:
Get-ADUser -Filter {UserAccountControl -ne 512} -Properties UserAccountControl | select Name,UserAccountControlTo resolve what the UAC value means, you can paste the number into this web tool
Or you can refer to this table:
| Value | Name |
|---|---|
| PASSWD_CANT_CHANGE | 64 |
| ENCRYPTED_TEXT__PWD_ALLOWED | 128 |
| TEMP_DUPLICATE_ACCOUNT | 256 |
| NORMAL_ACCOUNT | 512 |
| INTERDOMAIN_TRUST_ACCOUNT | 2048 |
| WORKSTATION_TRUST_ACCOUNT | 4096 |
| SERVER_TRUST_ACCOUNT | 8192 |
| DONT_EXPIRE_PASSWORD | 65536 |
| MNS_LOGON_ACCOUNT | 131072 |
| SMARTCARD_REQUIRED | 262144 |
| TRUSTED_FOR_DELEGATION | 524288 |
| NOT_DELEGATED | 1048576 |
| USE_DES_KEY_ONLY | 2097152 |
| DONT_REQ_PREAUTH | 4194304 |
| PASSWORD_EXPIRED | 8388608 |
| TRUSTED_TO_AUTH_FOR_DELEGATION | 16777216 |
| PARTIAL_SECRETS_ACCOUNT | 67108864 |
An easier way is to use powerview, which will resolve uac values for you
Get-DomainUser * | Select SAMAccountname,UserAccountControlDisabled user#
Get-ADUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=2)' | Select NameSometimes, a user can also be disabled by setting logonHours to 000000000000000000000. It was 21 bytes of 0, no need to count
We can query such users like this:
Get-ADUser -LDAPFilter '(logonHours=*)' -Properties * | Where {(logonHours -join '') -match '^0+$'}Groups#
Find admin groups#
Get-ADGroup -Filter "adminCount -eq 1" | Select NameMembers of group#
Enumerate members directly in Administrators group
(Get-ADGroup -identity "Administrators" -Properties *).Members
Get-ADGroup -identity "Administrators" -Properties * | Select Members | flEnumerate members indirectly (nested) and directly in Administrator group
Get-ADGroupMember -Identity "Administrator"Computers#
Domain Controllers#
Get-ADComputer -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=8192)'Trusted for delegation#
Get-ADComputer -Properties * -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' | Select DistinguishedName,SServicePrincipalName,TrustedForDelegation | fl