How to Use Graph Theory to automatically search for domain administrators
AD domain permission escalation is an important part of penetration testing. The commonly used domain permission escalation is centered on collecting plain text authentication information or tokens for your login system. This method is mainly implemented by Mimikatz. Generally, you can find the login information of the domain administrator on the machine you have obtained, and then you can directly collect the authentication information of the domain administrator and log on to the main system with these information.
However, if you are in a more complex environment and you have not obtained the Administrator permission for this machine, where is the domain administrator information? You may need to try them one by one so that you are getting farther and farther away from the domain administrator. At last, you need to try a lot of errors to find them.
In a recent penetration test, we initially only obtained domain user permissions. In this penetration environment, there were hundreds of workstations and servers, and several different domains managed each other. Our goal is to constantly expand the permissions and, if possible, get the permissions of the enterprise administrator. Fortunately, we have obtained a network topology. However, machines in the domain strictly follow the principle of minimizing permissions, which is almost zero error. After unremitting battles, we finally got a server administrator account, which we called "Steve-Admin" first ".
"Steve-Admin" is the local administrator of this server. We can find out which users have logged on to these servers. At this time, we need to determine which targets we will penetrate next. However, the user we log on to does not have the domain administrator permission or can't capture the domain administrator login information. We can only select one account randomly.
We found that this is an account with system administrator privileges, So we listed all the users who have logged on to this machine until we found the correct way. In a large network, this method may take days or even weeks.
In the following article, I will describe and demonstrate this automated process.
Preparations
The proof of this concept relies on existing tools and a group of diligent humans. The tools are as follows:
Schroeder (@ harmj0y) Do PowerView-https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1
Justin Warner (@ sixdub) Everywhere local administrator-http://www.sixdub.net /? P = 591
PowerShell Implementation of Dijkstra algorithm of Jim Truher (@ mongotruher)-https://jtruher3.wordpress.com/2006/10/16/dijkstra/
Emmanuel Gras and Lucas Bouillot are responsible for AD controller paths-https://github.com/ANSSI-FR/AD-control-paths
Justin Warner (@ sixdub) is responsible for domain node analysis-http://www.sixdub.net /? P = 285
Graph Theory
Imagine that we are not considering step-by-step upgrading from a "Steve-Admin" account to an enterprise administrator, but thinking about a path from Seattle in Washington to Portland in Oregon. For humans, looking at the map, we can easily see that no 5 is what we need. However, for computers, the path from Seattle to Portland must be calculated through mathematical computation (similar to the path from a "Steve-Admin" account to an enterprise administrator, provided that this path exists ).
PowerView can convert most of the data we give to the path from "Steve-Admin" to the enterprise administrator. The rest comes from the graph theory, a branch of mathematics proposed by Euler in the 18th century. Through graph theory, Euler proved that the seven bridges in kunisburg had no solution. This method includes:
Vertices-vertices (or nodes) represent a single element in a system. You can think of them as cities on a map.
Boundary-boundary is used to connect nodes. It can be directed or undirected.
Path-a path is a set of boundaries and nodes. nodes must be connected to each other.
Joining: nodes that share the same edge are called joining.
Graphic Design
There is only one purpose to prove the idea proposed to address this problem-to automatically find the shortest path of the compromised domain administrator. Of course, the design of this diagram may not be suitable for other problems.
At the beginning of this figure, I first designed it to be very simple and may be full of errors. With the continuous addition of machines, the final design was as follows:
Every user and machine is a node.
All edges are directed without weight.
The directed edge from the user to the machine represents the local administrator privilege.
A directed edge from a machine to a user represents a user who has logged on to the machine.
Imagine a very basic network structure with only two computers and two user groups. The "Administrator" user has the Administrator privilege for the two machines. One machine has a user named "mnelson" to log on. Visualized representation, such:
Every user and computer is a node. The orange line indicates that the Administrator account has the system Administrator permission for two computers. The blue line indicates that the mnelson user has logged on to the HR-WS-002. In this design, the edge direction means that the source node can break into the target node-the Administrator may break into the computer HR-WS-002, The HR-WS-002 may fall into the mnleson user.
Graph Construction
It is not easy to find the node of the graph, because we need to process every user and computer as a node. The simplest solution is to use two PowerView command sets Get-NetUser and Get-NetComputer:
The visualization of this image may look like the following:
Before calculating the Dijkstra algorithm, we first define the following attributes for these nodes:
Name: name of the node. For example: 'mnelson' or 'hr-WS-002'
Boundary: the boundary array of the node. Initial Value: $ null
Distance-the number of hops from the source node to the target node. The initial value is infinite. Note that this is an unweighted graph.
Accessed -- the shortest distance to the node is determined. Set initialization to $ False.
Precursor-name of the first node from The Source Vertex to the vertex in the path. Initialize to $ False
Next we will use the PowerView command set again, but this time we will use Get-NetSession. This command set can return the sessions information after we access a computer, which allows us to know which accounts have left session information on this computer, it also knows the machines on which these accounts belong, and these accounts do not require high permissions. With this information, we can expand our graph and enrich our graph. Next, we have the login information of each computer, recursively listing the user information of each machine. This information can further enrich the edge and node of our graph.
In our test environment, the result is structured as follows:
For example, user-> computer indicates the management permission, and computer-> user indicates the logged-on user.
Apparently, the "Administrator" account is the Administrator of three computers, and 'mnelson' users can manage OPS-WS-002 computers. User 'jwarner 'can manage IT-STV-002.
HR-WS-002 has a user login: mnelson. OPS-WS-002 has a user: jwarner. IT-SRV-002 has three login users: rwinchester, jfrank, and Administrator. Jdimmock is neither a manager nor a hacker.
Now we can use our existing information to find the shortest path.
Return to the case we mentioned earlier. Starting with 'Steve-admin', we can get a lot of computers and target users, but none of these users can find the domain administrator immediately. To avoid having to spend several days analyzing data one by one (even worse, if we use the trial and error method, it will be much more costly), we use an algorithm to calculate the shortest path.
Dijkstra Algorithm
The deeper I study the Dijkstra algorithm, the more fascinating I think it is. The Dijkstra algorithm can calculate the shortest path between each node in the graph on the provided nodes. These nodes only need to perform n cycles, and n indicates the number of vertices. The following is the workflow of Dijkstra algorithm:
1. Select a source node and set the distance value to 0. The distance from other nodes is assumed to be infinite.
2. Select the nearest unaccessed node and mark it as the current node.
3. Compare all edges of the current node. Compare the distance between all nodes adjacent to the current node and the current node, add 1 to the distance value, and compare the calculated distance value with the current value. If the distance value is smaller than the current value, update the distance value, update the value of adjacent nodes to the current node.
4. Go back to step 2 and know that all nodes are traversed.
After the algorithm is completed, you can know from the distance value of each node whether the node can reach the source node and how many hops are required to arrive. In addition, the process for finding the minimum path is as follows:
1. Add the name of the target node to our path array.
2. Add the nearest node to the array and find its previous hop. Add the previous hop to the array.
3. Execute these two steps cyclically. At this time, we have reached the source node.
Conclusion
Some of the methods described here are simple. There are many exciting ways to conduct AD attacks and defend against them through graph theory (or other mathematical techniques: for example, this article (https://cr0n1c.wordpress.com/2016/01/27/using-sccm-to-violate-best-practices ). For example, you can use the Administrator user as the source node to perform algorithm calculation by reversing the edge direction in the graph and obtaining more user information by using the management permission, you can calculate the Administrator account.
You can get the verified script from here: https://github.com/andyrobbins/PowerPath