Author: 风移
在SQL Server安全系列专题月报分享中,往期我们已经陆续分享了:如何使用对称密钥实现SQL Server列加密技术、使用非对称密钥实现SQL Server列加密、使用混合密钥实现SQL Server列加密技术、列加密技术带来的查询性能问题以及相应解决方案、行级别安全解决方案、SQL Server 2016 dynamic data masking实现隐私数据列打码技术、使用证书做数据库备份加密、SQL Server Always Encrypted和使用SSL加密连接这九篇文章,直接点击以上文章链接前往查看详情。本期月报我们分享SQL Server数据中,挑战云计算安全的几个存储过程。
在SQL Server数据库中,存在三种类型的存储过程:系统存储过程,用户定义存储过程和扩展存储过程。系统存储过程是SQL Server服务安装时在系统中创建的,以“sp_”打头;用户自定义存储过程是指用户编写的存储过程;扩展存储过程是 SQL Server服务可以动态加载和运行的 DLL,可直接在SQL Server 实例的地址空间中运行。做为云计算厂商,SQL Server数据库中内置的这些非常好用的扩展存储过程,也给数据库PaaS平台安全提出了新的挑战。因此,我们有必要深入分析这些存在安全风险的扩展存储过程和对应方案,它们涉及的面非常广泛,包括:
命令执行:在SQL Server中执行Windows命令
注册表操作:在SQL Server中操作注册表
OLE相关:在SQL Server中执行OLE相关动作
文件相关:在SQL Server中操作文件相关
执行命令的扩展存储过程,可以用来执行Windows操作系统的任何命令,只要在cmd里面能够做到的事情,都可以用它来执行。对,没错,它就是号称最最最为危险的存储过程xp_cmdshell,让我们来看看它的破坏力有多强。
在使用xp_cmdshell执行命令之前,请使用sys.sp_configure系统存储过程来启用它,如下所示:
USE master
GO
EXEC sys.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sys.sp_configure 'xp_cmdshell', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'show advanced options', 0
GO
我们可以使用xp_cmdshell来查看SQL Server所在的主机IP,轻松拿到主机IP地址。
EXEC master.sys.xp_cmdshell 'ipconfig'
如下图所示:
还可以创建文件,文件夹,查看文件夹中的内容,主机上文件暴露无遗。
EXEC master.sys.xp_cmdshell 'mkdir C:\tempfolder'
EXEC master.sys.xp_cmdshell 'dir C:\tempfolder'
如下所示:
更要命的是,我们还可以创建用户,比如创建用户IAmTestUser,
-- create user IAmTestUser
EXEC master.sys.xp_cmdshell 'net user IAmTestUser IAmTestUser@1 /add', no_output
GO
-- query users
EXEC master.sys.xp_cmdshell 'net user'
GO
如下图所示:
加到local Administrator组,然后想干什么就干什么了,如下:
-- add user IAmTestUser into local administrators group
EXEC master.sys.xp_cmdshell 'net localgroup administrators IAmTestUser /add', no_output
GO
当然,还可以删除用户,影响正常用户活动。
-- remove the testing user
EXEC master.sys.xp_cmdshell 'net user IAmTestUser /delete', no_output
GO
以上仅仅是几个小演示,这个扩展存储过程非常危险,给数据库安全带来了极大挑战,所以,测试完毕后,必须关闭。
USE master
GO
EXEC sys.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sys.sp_configure 'xp_cmdshell', 0
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'show advanced options', 0
GO
从这几个简单的演示,我们可以体会到xp_cmdshell的破坏威力之大,因此,作为SQL Server云计算服务提供者,这个扩展存储过程是绝对不允许开放给用户使用的。
Windows注册表(Registry)是Microsoft Windows系统中的一个非常重要的数据库,它用于存储Windows系统本身和应用程序的设置信息。Windows注册表的本身的安全至关重要的,而SQL Server中一些内置的可操作注册表的扩展存储过程,给注册表的安全保护,提出了挑战,包括:
xp_regwrite:写入注册表键值
xp_regdeletevalue:删除注册表中的值
xp_regdeletekey:删除注册表中的键
xp_regread:读取注册表中的值
这个扩展存储过程可以写入注册表指定的键里指定的值。假如,我们需要在键HKEY_LOCAL_MACHINE\SOFTWARE\aaaKey\aaaValueName中写入值aaaValue,请使用如下方法:
EXEC master.sys.xp_regwrite
@rootkey='HKEY_LOCAL_MACHINE',
@key='SOFTWARE\aaaKey',
@value_name='aaaValueName',
@type='REG_SZ',
@value='aaaValue'
;
结果展示如下:
这个扩展存储过程可以用来删除注册表中指定的键中指定的值。比如把我们刚才创建的键值HKEY_LOCAL_MACHINE\SOFTWARE\aaaKey\aaaValueName中的Value删除掉。方法如下:
EXEC master.sys.xp_regdeletevalue
@rootkey='HKEY_LOCAL_MACHINE',
@key='SOFTWARE\aaaKey',
@value_name='aaaValueName'
;
这个扩展存储过程可以删除注册表中指定的键,请小心谨慎使用。比如,删除我们刚才建立的测试注册表键HKEY_LOCAL_MACHINE\SOFTWARE\aaaKey。方法如下:
EXEC master.sys.xp_regdeletekey
@rootkey='HKEY_LOCAL_MACHINE',
@key='SOFTWARE\aaaKey'
;
这个扩展存储过程可以读取注册表指定的键中指定的值,获取一些重要的敏感信息。比如,如下实例是获取SQL Server服务所在主机的主机名。
DECLARE
@hostName sysname
;
EXEC master.sys.xp_regread
@rootkey='HKEY_LOCAL_MACHINE',
@key='system\controlset001\control\computername\computername',
@value_name='computername',
@value=@hostName OUTPUT
;
SELECT
@hostName AS [host_name]
;
SQL Server中内置的关于注册表操作的扩展存储过程,也给我们的数据库系统安全,甚至是操作系统的安全带来了极大挑战。做为云厂商及云服务的提供者,必须严防死守,把好安全关。
与OLE相关的一系列存储过程:sp_OACreate,sp_OADestroy,sp_OAGetErrorInfo,sp_OAGetProperty,sp_OAMethod,sp_OASetProperty,sp_OAStop。这些存储过程和xp_cmdshell危险等级一样高。我们也必须严加防范。以下仅以sp_OACreate和sp_OAMethod配合使用为例说明。
要使用OLE相关存储过程,必须先启用对OLE存储过程的使用,方法如下:
USE master
GO
EXEC sys.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sys.sp_configure 'Ole Automation Procedures', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'show advanced options', 0
GO
使用OLE存储过程,创建Windows的用户。
DECLARE
@shell INT
;
EXEC master.sys.sp_oacreate
'wscript.shell',
@shell OUTPUT
;
EXEC master.sys.sp_oamethod
@shell,
'run',
null,
'C:\Windows\System32\cmd.exe /c net user IAmTestUser IAmTestUser@1 /add'
;
使用OLE存储过程,将刚才创建Windows的用户添加到local Administrator组中,便有了系统超级用户的所有权限。
DECLARE
@id INT
;
EXEC master.sys.sp_oacreate
'wscript.shell',
@id OUTPUT
;
EXEC master.sys.sp_oamethod
@id,
'run',
null,
'C:\Windows\System32\cmd.exe /c net localgroup administrators IAmTestUser /add'
;
GO
当然,您可以删除用户。
DECLARE
@id INT
;
EXEC master.sys.sp_oacreate
'wscript.shell',
@id OUTPUT
;
EXEC master.sys.sp_oamethod
@id,
'run',
null,
'C:\Windows\System32\cmd.exe /c net user IAmTestUser /delete'
;
GO
OLE存储过程测试完毕后,必须禁用掉,以免带来极大的安全风险。
USE master
GO
EXEC sys.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sys.sp_configure 'Ole Automation Procedures', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'show advanced options', 0
GO
SQL Server中除了可以执行windows command的扩展存储过程,操作注册表的扩展存储过程,以及OLE扩展存储过程,还有一类文件操作的存储过程,比如:
xp_dirtree:查看文件目录结构
xp_subdirs:查看子文件夹
xp_fileexist:判断文件是否存储
xp_delete_file:删除备份文件
这个扩展存储过程用来列出对应目录下所有文件和文件夹。
EXEC master.sys.xp_dirtree N'C:\tempfolder'
xp_subdirs用来显示给定的文件夹下的所有子文件夹。
EXEC master.sys.xp_subdirs N'C:\tempfolder'
确认某个文件是否存在。
EXEC master.sys.xp_fileexist 'C:\tempfolder\01\Deadlock_0_131700921198410000.xel'
这个扩展存储过程用于删除数据库备份文件,如下所示:
BACKUP DATABASE DDLCenter TO DISK = N'C:\tempfolder\01\DDLCenter.bak'
EXEC master.sys.xp_delete_file 0, 'C:\tempfolder\01\DDLCenter.bak',N'.bak'
做为云计算厂商,为了保证SQL Server数据库平台的安全性,我们该如何应对这些高风险的扩展存储过程带给我们的安全挑战呢?我们的应对方案如下:
禁用扩展存储过程
删除扩展存储过程
拒绝扩展存储过程执行权限
有一些扩展存储过程属于是服务器外围配置选项,我们可以使用sys.sp_configure存储过程来开启和禁用它,这种方法在xp_cmdshell部分已经介绍过了,详情参见“开启xp_cmdshell”和“禁用xp_cmdshell”部分。
在SQL Server 2000及以前版本,我们还可以删除系统扩展存储过程,永绝后患。
EXEC master.sys.sp_dropextendedproc 'xp_cmdshell'
当然,删除后,你还是有后悔药可以再加回来
exec master.sys.sp_addextendedproc 'xp_cmdshell', 'C:\Program Files\Microsoft SQL Server\MSSQL\Binn\xplog70.dll'
而从SQL Server 2005开始,sys.sp_dropextendedproc不再支持对系统扩展存储过程的删除动作了,数据库管理员转而可以使用“拒绝扩展存储过程执行权限”的方式来达到相同的目的。
除了系统外围配置选项涉及的扩展存储过程可以通过sp_configure开启和禁用之外,剩下的系统扩展存储过程,我们只能通过拒绝PUBLIC角色可执行扩展存储过程权限的方式来禁用掉了,方法如下:
DENY EXECUTE ON sys.xp_regwrite TO PUBLIC;
此时,当用户再次执行写入注册表操作的时候,就会报告错误,比如:
EXEC master.sys.xp_regwrite
@rootkey='HKEY_LOCAL_MACHINE',
@key='SOFTWARE\aaaKey',
@value_name='aaaValueName',
@type='REG_SZ',
@value='aaaValue'
;
错误信息如下所示:
这样从根本上达到了安全防范的目的,保护了云厂商SQL Server数据库PaaS平台的安全性。
最后,看看我们如何去查找某一个特定的系统扩展存储过程的权限呢?在此,以我们刚才拒绝执行权限的扩展存储过程xp_regwrite为例说明,如下:
SELECT
schema_name(obj.schema_id) AS [schema_name],
obj.name AS [object_name],
obj.type,
b.permission_name,
B.type,
B.state_desc,
C.name,
c.type_desc
FROM sys.all_objects AS obj WITH(NOLOCK)
LEFT JOIN sys.database_permissions AS B WITH(NOLOCK)
ON B.major_id=obj.object_id AND B.minor_id=0 AND B.class=1
LEFT JOIN sys.database_principals AS C WITH(NOLOCK)
ON C.principal_id = B.grantee_principal_id
WHERE obj.name IN(SELECT object_name
FROM sys.system_components_surface_area_configuration AS x
WHERE x.type = 'X' AND x.object_name = 'xp_regwrite')
ORDER BY obj.name
结果展示如下:
从检查的结果来看,PUBLIC角色已经被拒绝EXECUTE权限,达到了目的。
本期月报我们分享了SQL Server数据库中几个有高安全风险的系统扩展存储过程,并没有完全罗列有安全风险的所有存储过程。保障云厂商SQL Server数据库PaaS平台的安全性,应对措施必不可少。