导语:Active Directory域权限升级是大多数渗透测试和红队攻击活动的重要组成部分。虽然获得域/企业管理员权限并不是安全评估的最终目标,但它通常能够更容易的实现渗透测试目标。
介绍
Active Directory域权限升级是大多数渗透测试和红队攻击活动的重要组成部分。虽然获得域/企业管理员权限并不是安全评估的最终目标,但它通常能够更容易的实现渗透测试目标。
典型的域权限提升过程围绕着收集明文凭据或登录到你已经拿到权限的系统并收集该系统中的用户的令牌,或者可以通过Mimikatz最有名的功能来获得提升的权限。找到一个登录到你拥有管理员权限的系统的域管理员,登录该系统,并收集管理员的凭据。
但是,如果你处于一个非常复杂的环境中,你不能立即在域管理员所在的系统上获得管理员权限,这时怎么办?你可能需要一次,两次,三次或更多次的在跳板机之间进行跳转,之后拿到域管理员,并需要做一些分析(或只是在试错)来找到你的渗透测试路径。
我们来看看一种假设的情况:我们在某个环境中获得了Domain User级别的权限,其中有数十万个工作站和服务器加入到了具有不同信任级别的多个域的Active Directory林中。如果可能的话,我们的目标就是将权限提升至企业管理员权限。幸运的是,网络拓扑结构比较简单; 然而,客户端执行了非常严格的最低特权措施。在争取找到提升权限的手段之后,我们终于可以拿到一个叫做“Steve-Admin”的服务器管理员帐户。
“Steve-Admin”是当前这台服务器上的本地管理员,我们需要将这个账户在其他地方也成为管理员。我们会拿这个服务器列表,找出哪些用户登录到了这些服务器上。然而,在这一点上,我们需要决定我们要选择哪个用户。我们可以拿到权限的登录用户都不是域管理员账户,也没有域管理员组的用户登录到这台服务器。我们必须选择一个帐户,找到这个账户具有管理权限的系统,枚举这些机器上的登录用户,并继续渗透,直到我们最终找到一个有效的路径。在具有成千上万台计算机和用户的环境中,该过程可能需要几天甚至几周的时间。
在这篇文章中,我会解释并展示如何自动化这个渗透过程。
先前的一些工作
这种思路的实现在很大程度上依赖于一些非常聪明且非常勤奋的人所公开分享的一些现有的工具和想法:
Will Schroeder 开发的PowerView(@harmj0y) – https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1
由Justin Warner发表的衍生的本地管理员的博文(@sixdub) – http://www.sixdub.net/?p=591
Jim Truher(@jwtruher)开发的Dijkstra算法的PowerShell实现 – https://jtruher3.wordpress.com/2006/10/16/dijkstra/
Emmanuel Gras和Lucas Bouillot发布的Active Directory控制路径 – https://github.com/ANSSI-FR/AD-control-paths
Justin Warner(@sixdub)的域信任的节点分析- http://www.sixdub.net/?p=285
可以想像一下,如果我们试图找到一条从“Steve-Admin”提权到企业管理的路径,而不是从华盛顿西雅图到俄勒冈州的波特兰找到一条路。作为一个人,你可以看一看地图,很容易确定5号州际公路可以让你到那里去。计算机可以找到西雅图和波特兰之间(以及“Steve-Admin”和企业管理员之间的路径,如果存在的话)。
PowerView可以为我们提供我们所需要的大部分数据,以便自动完成执行从“Steve-Admin”到Enterprise Admin的路径查找。而其余部分则是莱昂纳德·尤勒在18 个世纪建立的数学的一个分支,现在被称为图论。欧拉能够使用图形理论的现在标准的基础知识来证明没有解决柯尼斯堡问题的七桥。这些基本原则包括:
顶点 – 顶点(或节点)是用于表示所表示的系统的单个元素的点。你可以将地图上的城市视为顶点。
边缘 – 边缘用于连接顶点。可以引导边缘(即:单向)或无向(即:双向)。边缘一般代表一种关系。如果西雅图和波特兰被认为是顶点,I-5可以被认为是连接这些城市的双向边缘。
路径 – 路径是将一个节点连接到另一个节点的一组边和节点,无论这些节点是否相邻。
邻接 -共享边缘的顶点被认为是相邻的。
图形设计
我提出的这个问题的概念证明是设计了一个目标 – 自动化找到能拿到域管理员权限的最短路径的过程,而无需写入磁盘或需要离线分析。因此,该图的设计可能不适用于其他问题。
在设计这个图时,我主要关注简单性。经过无数次的失败,我终于得出了一个有用的设计:
每个用户和计算机都是顶点。
所有边缘均被定向和未加权。
从用户到计算机的有向边界指示本地管理员权限。
从计算机到用户的有向边缘指示登录的用户。
想象一下,一个非常基本的网络由两台电脑和两个用户组成。“管理员”帐户对这两个系统都有管理员权限。其中一个系统有一个用户“mnelson”登录。使用上述设计的该系统的视觉表示将如下图所示:
每个用户和计算机都是顶点。橙色边缘告诉我们,管理员帐户在两个系统上具有管理员权限。蓝色的边缘告诉我们,“mnelson”被登录到HR-WS-002上。在这种设计中,边缘总是意味着源顶点可能会损害目标顶点 – 管理员可以危及HR-WS-002和HR-WS-002(即:本机上的SYSTEM帐户)同时可能会使mnelson用户被入侵。
构建图
找到我们图的顶点不容易。因为我们将每个用户和计算机视为一个节点,它与使用两个PowerView cmdlet – Get-NetUser和Get-NetComputer一样简单:
此时图形的视觉表示可能如下所示:
为了准备运行Dijkstra的算法,我们给每个顶点以下属性:
名称 – 顶点的名称。示例:'mnelson'或'HR-WS-002'
边缘 – 这个顶点有一个边缘的顶点数组。最初设置为$Null。
距离 – 从源顶点到该顶点所需的跳数。最初设置为无限远。注意这是一个未加权的图。
被访问 – 是否确定了到该节点的最短距离。最初设置为$False。
前身 – 从源顶点到该顶点的路径中前一个顶点的名称。最初设置为$Null。
识别每个顶点的边缘稍微有点复杂。我们可以再次利用PowerView 的cmdlet – Get-NetSession。此cmdlet会返回我们运行的每台计算机的会话信息,让我们看到用户在该计算机上的会话以及该会话来自哪里,有效地允许我们确定哪些用户登录在哪里 – 所有的这些用户都没有提升过权限。使用这些信息,我们可以将边缘的计算机顶点填充到登录的用户。接下来,对于每台计算机,我们都有用户登录信息,我们递归地枚举该机器上的本地管理员用户。此信息允许我们使用边缘(指示本地管理员权限)填充相应的用户顶点到该计算机。
在我的测试实验室中,所有边缘的完成图可以像这样直观地表示:
回想一下,用户 – >计算机边缘表示管理员权限,计算机 – >用户边表示已登录的用户。
显然,“管理员”帐户是三台电脑中每一台计算机的管理员。“mnelson”用户是OPS-WS-002上的管理员。“jwarner”用户是IT-SRV-002的管理员。
HR-WS-002有一个用户登录:mnelson。OPS-WS-002有一个用户:jwarner。最后,具有三个登录用户的IT-SRV-002:rwinchester,jfrank和Administrator。jdimmock用户既不是管理员,也没有在任何地方登录(他可能在PTO上)。
我们现在有了我们需要找到从任何顶点到任何其他的最短路径的一切信息。
回想一下我之前概述的情况。从“Steve-Admin”,我们有几十台计算机和用户定位,没有一个可以让我们立即访问域管理员帐户。我们可以使用算法在几分钟内为我们找到该路径,而不是花费几个小时,几天甚至几周时间分析每个选项(或更糟糕的是,通过我们的选项进行试错)。
Dijkstra算法
我花更多的时间学习Dijkstra的算法,我越来越欣赏创造这种优雅,高效的方法的天才。Dijkstra的算法允许我们指定一个源顶点并找到图中每个其他顶点的最短路径,而且只需要n个循环,其中n是图中的顶点数。以下是Dijkstra算法的工作原理:
识别源顶点。将其距离设置为0.将每个其他顶点的距离设置为无穷大。
识别具有最小距离值的未访问的顶点,并将其标记为当前顶点。
考虑当前顶点的边。对于与当前顶点相邻的每个顶点,将其距离与当前顶点的距离加上一个值进行比较 – 如果此计算距离低于当前值,则更新相邻顶点的距离,并将相邻顶点的前导值更新为当前顶点。
转到步骤2,直到所有顶点都被访问。
一旦算法完成,每个顶点的距离值将告诉我们该顶点是否可以由源顶点到达,以及多少跳。另外,由于每个顶点的上一个属性,我们还可以回溯到我们的来源:
获取目标顶点的名称,并将其添加到我们的路径数组中。
将最近添加的顶点放在路径数组中,找到它的前身。将前导添加到路径数组。
重复,直到没有前身。在这一点上,我们已经达到了我们的源顶点。
结论和PoC
我们几乎没有入侵到这里的可能性。将图形理论(和其他数学领域)应用于Active Directory进攻和防御有一些非常令人兴奋的可能性(参见Brandon Helms aka cr0n1c:https ://cr0n1c.wordpress.com/2016/01/27 / using-sccm-to-violate-best-practices /)。例如,通过反转此图中每个边的方向,并使用管理员权限获取更多的登录用户数据,我们可以指定“管理员”用户作为源,并通过Dijkstra算法的一次迭代确定所有帐户AD可能会损害“管理员”帐户的路径。
你可以在这里找到概念证明: