前一段时间在内部网络的渗透测试期间,我遇到了物理分段网络。这些网络包含连接到相同Active Directory域的工作站,但是只有一个网络段可以连接到互联网。为了使用Cobalt Strike远程控制两个网段中的工作站,我构建了一个工具,该工具使用共享的Active Directory组件来构建通信通道。为此,它使用通常用于管理Active Directory的LDAP协议,从而通过LDAP有效地路由信标数据。这篇文章将详细介绍该工具的开发过程、工作方式并提供缓解建议。
几个月前,我对一位客户进行了网络渗透测试。这个客户端有多个完全防火墙化的网络,因此这些网络段之间不可能进行直接连接。由于成本/工作负载效率的原因,客户端选择在这些网络段之间使用相同的Active Directory域。
我们对A段和B段的工作站都有物理访问,在本文的示例中,A段的工作站可以访问互联网,而B段的工作站则不能访问互联网。虽然我们确实在两个网段的工作站上都有物理访问权限,但我们希望是通过互联网控制网络段B中的工作站。
Active Directory如何作为一个共享组件
两个网络段都能够连接到同一域中的域控制器,并且能够与对象交互、验证用户、查询信息等。在Active Directory中,用户帐户是可以添加额外信息的对象,此信息存储在属性中。默认情况下,用户帐户对其中一些属性具有写权限。例如,用户可以为自己的帐户更新个人信息,如电话号码或办公地点。此操作不需要任何特权,因为此信息对于身份SELF(即帐户本身)是可写的。如下面的屏幕截图所示,这是在Active Directory架构中配置的。
个人信息,例如电话号码或街道地址,对于互联网中每个经过身份验证的用户来说都是默认可读的,下面是显示经过身份验证的用户身份的公共信息权限的屏幕截图。
上面屏幕快照中的权限集提供了对个人信息属性集中定义的属性的访问,这个属性集包含40多个用户可以读取和写入的属性。完整的属性列表可以在该文章中找到。
默认情况下,在同一网络中中成功通过身份验证的每个用户都是“经过身份验证的用户”。这意味着我们可以使用Active Directory作为临时数据存储,并通过将数据写入这些属性,然后从其他网段读取数据,从而在两个隔离的网络之间交换数据。
如果我们有权访问用户帐户,则可以同时在两个网段中使用该用户帐户来通过Active Directory交换数据。不管工作站的安全设置如何,此方法都将起作用,因为该帐户将直接与域控制器而不是工作站进行通信。
要通过LDAP路由数据,我们首先需要在两个网段的工作站上都获得代码执行特权。但是,要实现这一目标,其过程就过于复杂,且超出了本文的讲述范围。
要通过LDAP路由数据,我们需要将数据写入其中一个属性,并从另一个网段读取数据。
在通常的情况下,我们要通过网络段A中的工作站在网络段B中的工作站上执行ipconfig,就必须将ipconfig命令写入属性,在网络段B中读取ipconfig命令,执行该命令并将结果写回属性。
该过程如下图所示:
注意,可以在我们的GitHub 页面上找到一个利用这个特性的示例脚本。
尽管实际上可以通过Active Directory在分段网络之间进行通信,但是该解决方案并不理想。例如,此通道取决于域控制器之间的数据复制。如果将消息写入域控制器A,再从域控制器B读取消息,则可能必须等待域控制器复制才能获取数据。另外,在上面的示例中,我们使用信息属性在Active Directory上交换数据。此属性最多可容纳1024个字节的信息,但是,如果有效载荷超过该大小怎么办?诸如此类的更多问题如果使该解决方案,则不理想。
最后,人们已经建立了一些概念证明,可以做同样的事情。 Harmj0y撰写了一篇有关此技术的文章,
这就是为什么我们决定构建一个高级LDAP通信通道来修复这些问题的原因。
构建高级LDAP通道
在上面的示例中,使用了信息属性。不过,这不是理想的解决方案,因为如果属性已经包含数据,或者数据最终出现在某个GUI中,情况又会怎样呢?
要查找其他属性,请查询Active Directory架构中的所有属性,以及:
1. 检查属性是否包含数据;
2. 如果用户对此具有写权限;
3. 如果内容可以清除。
如果全部检查完毕,该属性的名称和最大长度将存储在数组中,以备以后使用。
处理流程如下所示:
至于(有效载荷)数据未在GUI(例如通讯录)的某处结束,我们没有找到一种可靠的方法来检测属性是否在GUI中结束,因此像telephoneNumber这样的属性被添加到代码内的黑名单中。现在,出于速度和效率的考虑,从具有合适属性的数组中选择最大长度的属性。接下来,我们将这个属性称为“data-attribute(数据属性)”。
共享属性名
现在我们选择了数据属性,需要找到一种方法来将这个属性的名称从发送网络段共享到接收端。因为我们希望LDAP通道尽可能隐蔽,所以不想直接共享所选属性的名称。
为了克服这个困难,我们决定使用哈希。如前所述,为了选择合适的属性在LDAP上交换数据,对所有属性进行了查询。这些属性与属性名的CRC表示一起存储在哈希表中。如果在两个网段中都完成了此操作,则我们就可以共享哈希而不是属性名称,因为无论该域中使用了什么工具,哈希都将解析为属性的实际名称。
解决复制问题
LDAP通道的传输速率可能高于域控制器之间的复制率,解决这个问题的简单方法是与同一个域控制器通信。这意味着一个客户端必须选择一个域控制器,然后通过LDAP将域控制器的名称传达给另一个客户端。
完成此任务的方法与共享数据属性的名称相同,当该工具启动时,将查询所有域控制器并将其与域控制器的完全限定域名(FQDN)的CRC表示一起存储在哈希表中。与其他客户端共享已选择的域控制器的哈希,并将其解析为域控制器的实际FQDN。
原始共享数据
现在,我们有了一个属性来交换数据,就可以以一种混淆的方式共享属性的名称,并且可以通过与同一域控制器进行通信来避免复制问题。在进行通信之前,需要共享所有这些信息。
显然,如果我们尚未交换数据的属性,就无法共享此信息。
解决方案是利用一些可用作占位符的旧属性,对于该工具,我们选择使用以下属性· primaryInternationalISDNNumber
· otherFacsimileTelephoneNumber
· primaryTelexNumber
这些属性是个人信息属性集的一部分,并且自Windows 2000 Server开始就已成为其中的一部分,我们随机选择其中一个属性来存储原始数据。
不过,我们认为人们实际使用这些属性的机会很小。
本文,我们详细介绍了在LDAP属性的命令和控制过程中所遇到的一些问题,下一篇文章中,我们会接着介绍解决这些问题的办法。
本文翻译自:https://blog.fox-it.com/2020/03/19/ldapfragger-command-and-control-over-ldap-attributes/如若转载,请注明原文地址: