[Edit 8/13/15] – Here is how the old version 1.9 cmdlets in this post translate to PowerView 2.0:
- Get-NetGroup -> Get-NetGroupMember
- Get-NetGroups -> Get-NetGroup
[Note: This has been cross posted on the Adaptive Threat Division blog]
User hunting is one of my favorite phases of an engagement. Whether it’s performed for lateral spread and escalation, or to demonstrate impact by tracking down incident responders and executives, we end up hunting for users on nearly every assessment we go on. I presented on this topic at the Shmoocon ’15 Firetalks, and published the “I Hunt Sys Admins” post to help highlight some of the ways we use to track down where users are located in Windows domains.
One part of the user hunting process is gathering this raw location data from the network you’re operating in. The other component of the workflow, and something I haven’t covered as heavily, is identifying whom you want to actually target. While in some networks this is as straightforward as Get-NetGroup “Domain Admins”, it can get tricky when an organization has heavily delegated groups, separated roles, and a complex Active Directory structure. I wanted to cover a few tricks we’ve used recently to help us identify accounts to go after.
Searching for Groups
Let’s start with something basic. PowerView‘s Get-NetGroups accepts wildcards to search for names, which is quite useful for identifying groups of interest. For example, you can search for any groups with “admin” in the name by executing Get-NetGroups *admin*. We’ve had a lot of luck using this function to target who’s likely in charge of the data we’re after (i.e. Get-NetGroups *WidgetSiteDev*). You can also pipe this output to Get-NetGroup to enumerate a group’s members all in one swoop. For example, to target the Linux side of the house, we might do something like Get-NetGroups *linux* | Get-NetGroup :
Groups on Groups
One situation you might run into is heavily nested groups. Unwrapping the structure all the way down to the users you actually care about by performing a Get-NetGroup for every sub group, parsing any members that might be groups themselves, and so on can get to be painful in some environments. PowerView’s Get-NetGroup function now has a -Recurse flag, which will resolve any group members that might be groups themselves, continuing until all users are enumerated:
Separated Roles
Something else you might encounter is when an organization separates out administrative functionality into multiple user accounts for the same person. For example, a system administrator might have a ‘regular’ domain account used for email and normal operations, a separate ‘desktop admin’ account used for desktop administration, and a ‘server admin’ account used for specific server maintenance. This is a good security practice, as it segregates logical access and can make it a bit trickier for attackers.
However, with a bit of data correlation on AD user objects, we can pull out groupings of accounts likely owned by the same person. This is useful in two separate types of scenarios. First, you can use it in a top-down approach to figure out the regular user accounts potentially linked to high-value targets like Domain Admins. You can then spear phish a user’s ‘regular’ domain account in an attempt to compromise their elevated account, or search through user hunter data for any correlations. Second, you can take a bottom-up approach by taking user-hunting data and figuring out what high-value usernames might be linked to any of the ‘regular’ accounts found.
Often, related accounts will have some kind of similarity or link in one of the user object fields that can help you with grouping. The displayname property is a useful one that often preserves a similar pattern across all of a user’s accounts. We can extract this for input accounts, and then use Get-NetUser‘s new -Filter option to perform a wildcard search to return additional users. The -Filter flag takes normal ldap query syntax of the form (field=term), which allows you to search specific user fields quickly. For example, if I want to find all users with an email ending in a specific domain, I can run the following:
Get-NetUser -Filter "(userprincipalname=*@dev.testlab.local)" | Select-Object samaccountname,userprincipalname
Here’s how you might wrap this all up into a PowerView one-liner for a “Firstname Lastname” displayname format:
Get-NetGroup -GroupName "Domain Admins" | %{ Get-NetUser $_.membername } | %{ $a=$_.displayname.split(" ")[0..1] -join " "; Get-NetUser -Filter "(displayname=*$a*)" } | Select-Object -Property displayname,samaccountname
Let’s break this one-liner down piece by piece. I’m querying for all members of “Domain Admins” in my current domain, and for each result I’m extracting the resulting member/username and querying for the complete user object with Get-NetUser. For each of these results, I’m parsing out the displayname property, grabbing just the first two words using split and join, and then querying for any users that match that pattern for displayname (to search for linked accounts). Finally, I’m extracting just the displayname and accountname properties for display.
Depending on the network, you might need to use other fields or tweaks for correlation, so query your existing user with Get-NetUser and adjust accordingly.