If you’ve survived my last blog post, you know that Active Directory group structures can be used as powerful weapons by hackers. Our job as pen testers is to borrow these same techniques — in the form of PowerView — that hackers have known about for years, and then show management where the vulnerabilities live in their systems.
I know I had loads of fun building my AD graph structures. It was even more fun running my breadth-first-search (BFS) script on the graph to quickly tell me who the users are that would allow access to a file that I couldn’t enter with my current credentials.
The “Top Secret” directory on the Acme Salsa server was off limits with “Bob” credentials but available to anyone in the “Acme-Legal” group. The PowerShell script I wrote helped me navigate the graph and find the underlying users in Acme-Legal.
Closing My Graphs
If you think about this, instead of having to always search the same groups to find the leaf nodes, why not just build a table that has this information pre-loaded?
I’m talking about what’s known in the trade as the transitive closure of a graph. It sounds nerdier than it really needs to be: I’m just finding everything reachable, directly and indirectly, from any of the AD nodes in my graph structure.
I turned to brute-force to solve the closure problem. I simply modified my PowerShell scripts from last time to do a BFS from each node or entry in my lists and then collect everything I’ve visited. My closed graph is now contained in $GroupTC (see below).
Before you scream into your browsers, there are better ways do this, especially for directed graphs, and I know about the node sorting approach. The point here is to transcend your linear modes of thinking and view the AD environment in terms of connections.
Graph perfectionists can check this out.
Here’s a partial dump of my raw graph structure from last time:
And the same information, just for “Acme-VIPs”, that’s been processed with my closure algorithm:
Notice how the Acme-VIPs list has all the underlying users! If I had spent a little more time I’d eliminate every group in the search path from the list and just have the leaf nodes — in other words, the true list of users who can access a directory with Acme-VIPs access control permission.
Still, what I’ve created is quite valuable. You can imagine hackers using these very same ideas. Perhaps they log in quickly to run PowerView scripts to grab the raw AD group information and then leave the closure processing for large AD environments to an offline step.
There is an Easier Way to Do Closure
We can all agree that knowledge is valuable just for knowledge’s sake. And even if I tell you there’s a simpler way to do closure than I just showed, you’ll still have benefited from the deep wisdom gained from knowing about breadth first searches.
There is a simpler way to do closure.
As it turns out, PowerView cmdlets with a little extra PowerShell sauce can work out the users belonging to a top-level AD group in one long pipeline.
Get-NetGroupMember cmdlet that spews out all the direct underlying AD members? It also has a
–Recurse option that performs the deep search that I accomplished with the breadth-first-search algorithm above.
To remove the AD groups in the search path that my algorithm didn’t, I can filter on the IsGroup field, which conveniently has a self-explanatory name. And since users can be in multiple groups (for example, Cal), I want a unique list. To rid the list of duplicates, I used PowerShell’s
get-object –unique cmdlet.
Now for the great reveal: my one line of PS code that lists the true users who are underlying a given AD Group, in this case Acme-VIPs:
This is an amazing line of PowerShell for pen testers (and hackers as well), allowing them to quickly see who are the users worth going after.
Thank you Will Schroeder for this PowerView miracle!
It’s a good time to step back, take a deep breath, and look at the big picture. If you—IT security or admin team—don’t do the work of minimizing who has access to a directory, the hackers will effectively do if for you. I’ve just shown that with PowerView, they have tools to make this happen.
Of course, you bring in pen testers to discover these permission gaps and other security holes before the hackers.
Or there is another possibility.
Our blog’s generous sponsor, Varonis Systems, has been making beautifully crafted data access and governance solutions since Yaki Faitelson and Ohad Korkus set up shop in 2004. Their DatAdvantage solution has been helping IT admins and security pros find the underlying users who have access to files and directories.
Varonis: For over ten years, they’ve been saving IT from writing complicated breadth-first-search scripts!
Taking the Derivative of the Admin
Back to our show.
Two blog posts ago, I began to show how PowerView can help pen testers hop around the network. I didn’t go into much detail.
Now for the details.
Their exploit hinges on two facts of life in AD environments. One, many companies have grown complex AD group structures. And they often lose track of who’s in which group.
Second, they configure domain-level groups to be local administrators of user workstations or servers. This is a smart way to centralize local administration of Windows machines without requiring the local administrator to be a domain-level admin.
For example, I set up special AD groups Acme-Server1, Acme-Server2, and Acme-Server3 that are divided up among the Acme IT admin team members — Cal, Meg, Rodger, Lara, and Camille.
In my simple Acme network, I assigned these AD groups to Salsa (Acme-Server1), Avocado (Acme-Server3), and Enchilada (Acme-Server2) and placed them under the local Administrators group (using lusrmgr.msc).
In large real-world networks, IT can deploy many AD groups to segment the Windows machines in large corporate environments — it’s a good way to limit the risks if an admin credential has been taken.
In my Acme environment, Cal who’s a member of Acme-Server1, uses his ordinary domain user account to log into Salsa and then gain admin privileges to do power-user level work.
By using this approach, though, corporate IT may have created a trap for themselves.
There’s a PowerView command called
Get-NetLocalGroup that discovers these local admins on a machine-by-machine basis.
Get-NetLocalGroup effectively tells you that specific groups and users are tied to specific machines, and these users are power users!
So as a smart hacker or pen tester, you can try something like the following as a lateral move strategy. Use
Get-NetLocalGroup to find the groups that have local admin access on the current machine. Then do the same for other servers in the neighborhood to find those machines that share the same groups.
You can dump the hashes of users in the local admin group of the machine you’ve landed on and then freely jump to any machine that
Get-NetLocalGroup tells you has the same domain groups!
So once I dump and pass the hash of Cal, I can hop to any machine that uses Acme-Server1 as local admin group.
By the way, how do you figure out definitively all the admin users that belong to Acme-Server1?
Answer: use the one-line script that I came up with above that does the drill-down and apply it to the results of
And, finally, where does derived or derivative admin come into play?
If you’re really clever, you might make the safe assumption that IT occasionally puts the same user in more than one admin group.
As a pen tester, this means you may not be restricted to only the machines that the users in the local admin domain group of your current server have access to!
To make this point, I’ve placed Cal in Acme-Server1 and Acme-Server2, and Meg in Acme-Server2 and Acme-Server3.
If you’re following along at home, that means I can use Cal to hop from Salsa to Avocado. On Avocado, I use Meg’s credentials to then jump from Avocado to Enchilada.
On the surface it appears that my teeny three-machine network was segmented with three AD groups, but in fact there were hidden connections —Cal and Meg — that broke through these surface divisions.
So Cal in Acme-Server1 can get to an Acme-Server3 machine, and is ultimately considered a derivative admin of Enchilada!
If you’re thinking in terms of connections, rather than lists, you’ll start seeing this as a graph search problem that is very similar in nature to what I presented in the last post.
This time, though, you’ll have to add into the graph, along with the users, the server names. In our make-believe scenario, I’ll have adjacency lists that tell me that Salsa is connect to Cal; Avocado is connected to Cal, Meg, Lara, and Roger; and Enchilada is connected to Meg and Camille.
I’ve given you enough clues to work out the PowerView and PowerShell code for the derivative admin graph code, which I’ll show next time.
As you might imagine, there can be lots of paths through this graph from one machine to another. There is a cool idea, though, that helps make this problem easier.
In the meantime, if you want to cheat a little to see how the pros worked this out, check out Andy Robbins’ code.