资讯专栏INFORMATION COLUMN

通过登陆触发器与防火墙限制登陆IP

hqman / 3213人阅读

摘要:脚本功能说明自动删除重名数据库,然后创建自动创建登陆管理表自动删除重名的登陆触发器,然后重新创建。如果身份验证失败,将不激发登录触发器。如果由其他例程调用即使这些例程由或登录触发器进行调用,将返回。

查看数据库日志发现好多非法登陆失败的记录,虽然之前已经更改了服务器和数据库的管理员账户的用户名,但是为了保险起见,还是再加上一道措施。创建登录触发器,只允许指定的IP访问,服务器设置白名单,但是这只适用于访问用户的IP固定不会经常变更的情况。而我们的开发服务器却不符合这种情况,只能想办法实施一个动态的管理方案。

声明:本文为Willem(Mongo)原创,转载请注明原文链接:https://segmentfault.com/a/11...。

为节省您的宝贵时间,请直接看触发器2.0 + SQL变更入站规则即可,有问题可先参照问题汇总。如有其他问题请在评论中留言,一起探讨。谢谢!

网上有文章(点击查看) 写的很详细,这里就不赘述了。下面的SQL是创建数据库触发器时给的默认模板,根据自己的情况进行修改:

</>复制代码

  1. --====================================
  2. -- Create database trigger template
  3. --====================================
  4. USE
  5. GO
  6. IF EXISTS(
  7. SELECT *
  8. FROM sys.triggers
  9. WHERE name = N""
  10. AND parent_class_desc = N"DATABASE"
  11. )
  12. DROP TRIGGER ON DATABASE
  13. GO
  14. CREATE TRIGGER ON DATABASE
  15. FOR
  16. AS
  17. IF IS_MEMBER ("db_owner") = 0
  18. BEGIN
  19. PRINT "You must ask your DBA to drop or alter tables!"
  20. ROLLBACK TRANSACTION
  21. END
  22. GO
登陆触发器的创建脚本 v1.0

下面这个脚本只能DBA自己先向IP管理表插入允许访问数据库的IP,因为登陆触发器只有身份验证通过时才能触发,所以暂时没去记录非法登陆失败的IP:

</>复制代码

  1. /**登录触发器将在登录的身份验证阶段完成之后且用户会话实际建立之前激发。如果身份验证失败,将不激发登录触发器。**/
  2. USE [master]
  3. GO
  4. /****** Object: Table [dbo].[ManagerIP] Script Date: 2016年10月13日11:31:22 ******/
  5. SET ANSI_NULLS ON
  6. GO
  7. SET QUOTED_IDENTIFIER ON
  8. GO
  9. --将数据库回滚到原始配置状态,然后删除
  10. IF DB_ID("LoginIP") IS NOT NULL
  11. ALTER DATABASE LoginIP SET SINGLE_USER WITH ROLLBACK IMMEDIATE
  12. DROP DATABASE LoginIP
  13. GO
  14. --创建数据库
  15. CREATE DATABASE [LoginIP]
  16. GO
  17. USE [LoginIP]
  18. GO
  19. --创建IP管理表
  20. CREATE TABLE [dbo].[ManagerIP](
  21. [IP] [nvarchar](15) NOT NULL,
  22. [BlockState] [bit] NOT NULL,
  23. [FalseCount] [int] NOT NULL,
  24. [UpdateTime] [datetime] NULL,
  25. [TotalTimes] [int] NOT NULL,
  26. CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED
  27. (
  28. [IP] ASC
  29. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  30. ) ON [PRIMARY]
  31. GO
  32. --插入允许通过的IP
  33. INSERT INTO dbo.ManagerIP
  34. ( IP ,
  35. BlockState ,
  36. FalseCount ,
  37. UpdateTime ,
  38. TotalTimes
  39. )
  40. VALUES ( N"" , -- IP - nvarchar(15)
  41. 0 , -- BlockState - bit
  42. 0 , -- FalseCount - int
  43. GETDATE() , -- UpdateTime - datetime
  44. 0 -- TotalTimes - int
  45. )
  46. INSERT INTO dbo.ManagerIP
  47. ( IP ,
  48. BlockState ,
  49. FalseCount ,
  50. UpdateTime ,
  51. TotalTimes
  52. )
  53. VALUES ( N"221.227.108.132" , -- IP - nvarchar(15)
  54. 0 , -- BlockState - bit
  55. 0 , -- FalseCount - int
  56. GETDATE() , -- UpdateTime - datetime
  57. 0 -- TotalTimes - int
  58. )
  59. GO
  60. USE master
  61. GO
  62. --删除触发器(注意:登陆触发器是存放在sys.server_triggers ,而不是sys.triggers
  63. IF EXISTS(SELECT * FROM sys.server_triggers WHERE name = "check_login_ip") --AND parent_class_desc = N"LoginIP")
  64. DROP TRIGGER check_login_ip ON ALL SERVER
  65. GO
  66. --创建触发器
  67. --CREATE TRIGGER trigger_name ON LoginIP
  68. CREATE TRIGGER check_login_ip ON ALL SERVER
  69. FOR LOGON
  70. AS
  71. IF IS_SRVROLEMEMBER ("sysadmin") = 1
  72. BEGIN
  73. DECLARE @ip NVARCHAR(15);
  74. --只有直接在 DDL 或登录触发器内部引用 EVENTDATA 时,EVENTDATA 才会返回数据。 如果 EVENTDATA 由其他例程调用(即使这些例程由 DDL 或登录触发器进行调用),将返回 NULL
  75. SET @ip = (SELECT EVENTDATA().value("(/EVENT_INSTANCE/ClientHost)[1]","NVARCHAR(15)"));
  76. IF NOT EXISTS(SELECT IP FROM [LoginIP].[dbo].[ManagerIP] WHERE IP = @ip)
  77. ROLLBACK TRANSACTION;
  78. END
  79. GO

相关链接:
点击查看关于“EVENTDATA() ”的说明;
点击查看“Sql Server中判断表或者数据库是否存在 ”
点击查看“IS_SRVROLEMEMBER("sysadmin") ”的详细说明
点击查看“登录触发器”的详细说明
点击查看“sys.server_triggers”的详细说明
点击查看“sys.triggers”的详细说明

上述脚本复制到SQL Server直接执行就可以。
脚本功能说明:自动删除重名数据库,然后创建;自动创建登陆IP管理表;自动删除重名的登陆触发器,然后重新创建。

登陆触发器的创建脚本 v2.0

上面提到了关于允许访问数据库的IP的管理问题,1.0 版本只能手动操作,而不能动态的自行管理IP,这样就造成了不够灵活的问题。
问题产生的情景:
如果我在表中添加了家里和公司的IP,光是这就很麻烦,因为要去统计开发人员家中的IP地址,更何况一旦到客户现场演示时,IP又无法添加,只能让已添加的IP进入数据库手动添加,实在有些麻烦。但是又不得不去设置,因为查看一下数据库记录就不难看到,每天都会有很多外界的IP来光顾,虽然还未成功,但难保哪天被黑了。

需求:来访IP记入IP管理表,连续登陆失败超过设定的次数就将该IP设置为黑名单,可以防止其暴力破解数据库密码。如果未超过设定次数登陆成功,则将失败次数清0。听起来跟输入银行密码的感觉差不多。下面是最终的逻辑图:

又经过了一天半的时间,产生了下面最终的脚本,可以动态控制IP,这里的动态是相对前面的静态而言;

</>复制代码

  1. /**登录触发器将在登录的身份验证阶段完成之后且用户会话实际建立之前激发。如果身份验证失败,将不激发登录触发器。**/
  2. USE [master]
  3. GO
  4. /****** Object: Table [dbo].[ManagerIP] Script Date: 2016年10月13日11:31:22 ******/
  5. SET ANSI_NULLS ON
  6. GO
  7. SET QUOTED_IDENTIFIER ON
  8. GO
  9. --创建IP管理表
  10. IF OBJECT_ID (N"dbo.ManagerIP", N"U") IS NULL
  11. BEGIN
  12. CREATE TABLE [dbo].[ManagerIP](
  13. [IP] [nvarchar](15) NOT NULL,
  14. [LockState] [bit] NOT NULL,
  15. [FalseCount] [int] NOT NULL,
  16. [UpdateTime] [datetime] NULL,
  17. [TotalTimes] [int] NOT NULL,
  18. CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED
  19. (
  20. [IP] ASC
  21. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  22. ) ON [PRIMARY];
  23. END
  24. GO
  25. --插入允许通过的IP
  26. IF (SELECT COUNT(*) FROM dbo.ManagerIP) = 0
  27. BEGIN
  28. INSERT INTO dbo.ManagerIP
  29. ( IP ,
  30. LockState ,
  31. FalseCount ,
  32. UpdateTime ,
  33. TotalTimes
  34. )
  35. VALUES ( N"" , -- IP - nvarchar(15)
  36. 0 , -- BlockState - bit
  37. 0 , -- FalseCount - int
  38. GETDATE() , -- UpdateTime - datetime
  39. 0 -- TotalTimes - int
  40. );
  41. END
  42. GO
  43. --删除触发器(注意:登陆触发器是存放在sys.server_triggers ,而不是sys.triggers
  44. IF EXISTS(SELECT * FROM sys.server_triggers WHERE name = "check_login_ip")
  45. BEGIN
  46. DROP TRIGGER check_login_ip ON ALL SERVER
  47. END
  48. GO
  49. --创建触发器
  50. --CREATE TRIGGER trigger_name ON LoginIP
  51. CREATE TRIGGER check_login_ip ON ALL SERVER
  52. FOR LOGON
  53. AS
  54. IF IS_SRVROLEMEMBER ("sysadmin") = 1
  55. BEGIN
  56. DECLARE @ip NVARCHAR(15);
  57. --只有直接在 DDL 或登录触发器内部引用 EVENTDATA 时,EVENTDATA 才会返回数据。 如果 EVENTDATA 由其他例程调用(即使这些例程由 DDL 或登录触发器进行调用),将返回 NULL
  58. SET @ip = (SELECT EVENTDATA().value("(/EVENT_INSTANCE/ClientHost)[1]","NVARCHAR(15)"));
  59. IF (SELECT COUNT(*) FROM [master].[dbo].[ManagerIP] WHERE IP = @ip AND LockState = 1) > 0
  60. BEGIN
  61. ROLLBACK;
  62. END
  63. ELSE IF (SELECT COUNT(*) FROM [master].[dbo].[ManagerIP] WHERE IP = @ip AND LockState = 0) > 0
  64. BEGIN
  65. UPDATE [master].[dbo].[ManagerIP] SET UpdateTime = GETDATE() WHERE IP = @ip;
  66. SET NOEXEC ON;
  67. END
  68. --删除临时表
  69. ELSE IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL
  70. BEGIN
  71. DROP TABLE #ErrorLog;
  72. END
  73. --创建临时表
  74. CREATE TABLE #ErrorLog(
  75. [LogDate] [datetime],
  76. [ProcessInfo] [nvarchar](200),
  77. [Text] [NVARCHAR](1000)
  78. );
  79. --读取当前日志插入到临时表
  80. INSERT INTO #ErrorLog EXEC sp_readerrorlog 0,1,"匹配",@ip;
  81. -- @p1 = 0, -- int 0为当前日志,1-9为对应编号日志
  82. -- @p2 = 1, -- int 1为服务器日志,2为代理日志
  83. -- @p3 = N"", -- nvarchar(4000) 包含的第一个字段
  84. -- @p4 = N"" -- nvarchar(4000) 包含的第二个字段
  85. DECLARE @TotalFalse int
  86. SET @TotalFalse = (SELECT COUNT(*) FROM #ErrorLog);
  87. IF @TotalFalse < 5
  88. BEGIN
  89. INSERT INTO [dbo].[ManagerIP] ([IP], [LockState], [FalseCount], [UpdateTime], [TotalTimes])
  90. VALUES (@ip, 0, 0, GETDATE(), 0);
  91. SET NOEXEC ON;
  92. END
  93. ELSE
  94. BEGIN
  95. INSERT INTO [dbo].[ManagerIP] ([IP], [LockState], [FalseCount], [UpdateTime], [TotalTimes])
  96. VALUES (@ip, 1, 0, GETDATE(), 0);
  97. END
  98. END
  99. GO

参考资料:
点击查看“捕获登录触发器事件数据”;
点击查看“GETDATE”;
点击查看“OBJECT_ID”;

将当前日志中已存在的非法IP导入数据库

SQL如下:

</>复制代码

  1. USE master
  2. GO
  3. --设置允许错误密码的最大次数
  4. DECLARE @MaxFalse int;
  5. SET @MaxFalse = 10;
  6. --删除日志临时表
  7. IF OBJECT_ID(N"tempdb..#LogTemp") IS NOT NULL
  8. BEGIN
  9. DROP TABLE #LogTemp;
  10. END
  11. --创建日志临时表
  12. CREATE TABLE #LogTemp(
  13. [LogDate] [datetime],
  14. [ProcessInfo] [nvarchar](200),
  15. [Text] [NVARCHAR](1000)
  16. );
  17. --删除错误日志临时表
  18. IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL
  19. BEGIN
  20. DROP TABLE #ErrorLog;
  21. END
  22. --创建错误日志临时表
  23. CREATE TABLE #ErrorLog(
  24. [ClientIP] [NVARCHAR](150),
  25. [TotalFalse] [int]
  26. );
  27. --从日志临时表筛选出登陆错误的日志记录
  28. INSERT INTO #LogTemp EXEC sp_readerrorlog 0,1,"匹配","客户端";
  29. --对错误日志进行统计
  30. INSERT INTO #ErrorLog SELECT el.Text,COUNT(*) FROM #LogTemp AS el GROUP BY el.Text
  31. DROP TABLE #LogTemp
  32. DECLARE @clientiptext nvarchar(150)
  33. DECLARE @total INT
  34. DECLARE @ipstr nvarchar(15)
  35. WHILE EXISTS ( SELECT ClientIP FROM #ErrorLog WHERE TotalFalse > @MaxFalse)
  36. BEGIN
  37. SELECT TOP 1 @clientiptext = logs.ClientIP, @total = logs.TotalFalse FROM #ErrorLog AS logs WHERE logs.TotalFalse > @MaxFalse;
  38. DELETE #ErrorLog WHERE ClientIP = @clientiptext;
  39. SET @ipstr = SUBSTRING(@clientiptext,CHARINDEX("客户端",@clientiptext) + 5,LEN(@clientiptext) - CHARINDEX("客户端",@clientiptext) - 5);
  40. IF NOT EXISTS ( SELECT * FROM dbo.ManagerIP WHERE IP = @ipstr )
  41. BEGIN
  42. INSERT INTO dbo.ManagerIP
  43. ( IP ,
  44. LockState ,
  45. FalseCount ,
  46. UpdateTime ,
  47. TotalTimes
  48. )
  49. VALUES ( @ipstr , -- IP - nvarchar(15)
  50. 1 , -- LockState - bit
  51. @total , -- FalseCount - int
  52. GETDATE() , -- UpdateTime - datetime
  53. 0 -- TotalTimes - int
  54. )
  55. END
  56. ELSE IF @total < (SELECT FalseCount FROM dbo.ManagerIP)
  57. BEGIN
  58. UPDATE dbo.ManagerIP SET FalseCount += @total WHERE IP = @ipstr
  59. END
  60. ELSE
  61. BEGIN
  62. UPDATE dbo.ManagerIP SET FalseCount = @total WHERE IP = @ipstr
  63. END
  64. END
  65. DROP TABLE #ErrorLog
  66. GO
依然存在的问题

这样看起来是没问题了,但是这样做并没能防止其他人暴力破解密码,只是破解之后不能通过该IP访问数据库而已,原因之前也提到了,登录触发器只能在验证通过后才能激活,反应到实际操作中就是通过验证和未通过验证的提示是不同的,只要发现问题提示发生的变化就可以根据这个来判断账户和密码是否正确,当然最好的做法就是不要对外开放数据库。不过这样做就会让开发人员麻烦些。现在的问题就是如何可以将定为非法的IP阻止在验证之前。这里想到的一个做法是将该IP放到防火墙阻止列表中,这样的话无法通过防火墙,那么就不会访问数据库,也就不会进行验证了。

</>复制代码

  1. 因为前面的操作都配合触发器、计划任务或者维护计划进行了自动化,所以这样也要做到自动向防火墙中添加IP,这样就需要脚本来进行操作了。而可以操作防火墙的指令:
  2. C:Windowssystem32>netsh advfirewall firewall add rule ?
  3. 用法: add rule name=
  4. dir=in|out
  5. action=allow|block|bypass
  6. [program=]
  7. [service=|any]
  8. [description=]
  9. [enable=yes|no (default=yes)]
  10. [profile=public|private|domain|any[,...]]
  11. [localip=any|||||]
  12. [remoteip=any|localsubnet|dns|dhcp|wins|defaultgateway| ||||]
  13. [localport=0-65535|[,...]|RPC|RPC-EPMap|IPHTTPS|any (default=any)]
  14. [remoteport=0-65535|[,...]|any (default=any)]
  15. [protocol=0-255|icmpv4|icmpv6|icmpv4:type,code|icmpv6:type,code| tcp|udp|any (default=any)]
  16. [interfacetype=wireless|lan|ras|any]
  17. [rmtcomputergrp=]
  18. [rmtusrgrp=]
  19. [edge=yes|deferapp|deferuser|no (default=no)]
  20. [security=authenticate|authenc|authdynenc|authnoencap|notrequired (default=notrequired)]
  21. 备注:
  22. - 将新的入站或出站规则添加到防火墙策略。
  23. - 规则名称应该是唯一的,且不能为 "all"
  24. - 如果已指定远程计算机或用户组,则 security 必须为 authenticate、authenc、authdynenc 或 authnoencap。
  25. - 为 authdynenc 设置安全性可允许系统动态协商为匹配 给定 Windows 防火墙规则的通信使用加密。 根据现有连接安全规则属性协商加密。选择此选项后,只要入站 IPSec 连接已设置安全保护, 但未使用 IPSec 进行加密,计算机就能够接收该入站连接的第一个 TCP 或 UDP 包。一旦处理了第一个数据包,服务器将重新协商连接并对其进行升级,以便所 有后续通信都完全加密。
  26. - 如果 action=bypass,则 dir=in 时必须指定远程计算机组。
  27. - 如果 service=any,则规则仅应用到服务。
  28. - ICMP 类型或代码可以为 "any"
  29. - Edge 只能为入站规则指定。
  30. - AuthEnc 和 authnoencap 不能同时使用。
  31. - Authdynenc 仅当 dir=in 时有效。
  32. - 设置 authnoencap 后,security=authenticate 选项就变成可选参数。
  33. 示例:
  34. 为不具有封装的 messenger.exe 添加入站规则:
  35. netsh advfirewall firewall add rule name="allow messenger" dir=in program="c:programfilesmessengermsmsgs.exe" security=authnoencap action=allow
  36. 为端口 80 添加出站规则:
  37. netsh advfirewall firewall add rule name="allow80" protocol=TCP dir=out localport=80 action=block
  38. 为 TCP 端口 80 通信添加需要安全和加密的入站规则:
  39. netsh advfirewall firewall add rule name="Require Encryption for Inbound TCP/80" protocol=TCP dir=in localport=80 security=authdynenc action=allow
  40. messenger.exe 添加需要安全的入站规则:
  41. netsh advfirewall firewall add rule name="allow messenger" dir=in program="c:program filesmessengermsmsgs.exe" security=authenticate action=allow
  42. 为 SDDL 字符串标识的组 acmedomainscanners 添加经过身份验证的防火墙跳过规则:
  43. netsh advfirewall firewall add rule name="allow scanners" dir=in rmtcomputergrp= action=bypass security=authenticate
  44. 为 udp- 的本地端口 5000-5010 添加出站允许规则
  45. Add rule name="Allow port range" dir=out protocol=udp localport=5000-5010 action=allow

通过帮助信息,我们可以了解到其中各个参数的含义及用途。而我们所需要达到的目的是:防止某IP访问该服务器上的数据库。对照上面翻译成简单的脚本就是:

</>复制代码

  1. netsh advfirewall firewall add rule name=BlockIP dir=in action=block description=阻止访问服务器数据库,甚至所有程序。 enable=yes remoteip=115.29.77.97

而我们需要把所有需要阻止的IP都要加入该规则中的 remoteip 中。不过在执行过程中出现了权限限制的问题,退而求其次,将bat命令存储为bat文件。

SQL输出bat文件

这种做法比较恶心,因为还要计划任务去调用执行,而且保存的文件还有问题,因为复制其中的命令到新建的bat文件中可以正常执行,但是直接执行该文件则有问题。不推荐此种方法,请查看下一种方法。

</>复制代码

  1. USE master
  2. GO
  3. --设置允许错误密码的最大次数
  4. DECLARE @MaxFalse int;
  5. SET @MaxFalse = 66;
  6. --删除日志临时表
  7. IF OBJECT_ID(N"tempdb..#LogTemp") IS NOT NULL
  8. BEGIN
  9. DROP TABLE #LogTemp;
  10. END
  11. --创建日志临时表
  12. CREATE TABLE #LogTemp(
  13. [LogDate] [datetime],
  14. [ProcessInfo] [nvarchar](200),
  15. [Text] [NVARCHAR](1000)
  16. );
  17. --删除错误日志临时表
  18. IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL
  19. BEGIN
  20. DROP TABLE #ErrorLog;
  21. END
  22. --创建错误日志临时表
  23. CREATE TABLE #ErrorLog(
  24. [ClientIP] [NVARCHAR](150),
  25. [TotalFalse] [int]
  26. );
  27. --从日志临时表筛选出登陆错误的日志记录
  28. INSERT INTO #LogTemp EXEC sp_readerrorlog 0,1,"匹配","客户端";
  29. --对错误日志进行统计
  30. INSERT INTO #ErrorLog SELECT el.Text,COUNT(*) FROM #LogTemp AS el GROUP BY el.Text
  31. DROP TABLE #LogTemp
  32. DECLARE @clientiptext nvarchar(150)
  33. DECLARE @total int
  34. DECLARE @ipstr nvarchar(15)
  35. DELETE FROM ManagerIP WHERE FalseCount < @MaxFalse AND LockState = 1
  36. WHILE EXISTS ( SELECT ClientIP FROM #ErrorLog WHERE TotalFalse > @MaxFalse)
  37. BEGIN
  38. SELECT TOP 1 @clientiptext = logs.ClientIP, @total = logs.TotalFalse FROM #ErrorLog AS logs WHERE logs.TotalFalse > @MaxFalse;
  39. DELETE #ErrorLog WHERE ClientIP = @clientiptext;
  40. SET @ipstr = SUBSTRING(@clientiptext,CHARINDEX("客户端",@clientiptext) + 5,LEN(@clientiptext) - CHARINDEX("客户端",@clientiptext) - 5);
  41. IF NOT EXISTS ( SELECT * FROM dbo.ManagerIP WHERE IP = @ipstr )
  42. BEGIN
  43. INSERT INTO dbo.ManagerIP
  44. ( IP ,
  45. LockState ,
  46. FalseCount ,
  47. UpdateTime ,
  48. TotalTimes
  49. )
  50. VALUES ( @ipstr , -- IP - nvarchar(15)
  51. 1 , -- LockState - bit
  52. @total , -- FalseCount - int
  53. GETDATE() , -- UpdateTime - datetime
  54. 0 -- TotalTimes - int
  55. )
  56. END
  57. END
  58. DROP TABLE #ErrorLog;
  59. EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35)
  60. @configvalue = 1; -- int
  61. GO
  62. RECONFIGURE;
  63. GO
  64. EXEC sys.sp_configure @configname = "Ole Automation Procedures", -- varchar(35)
  65. @configvalue = 1; -- int
  66. GO
  67. RECONFIGURE;
  68. GO
  69. DECLARE @blockips nvarchar(MAX) = "";
  70. DECLARE @tempip nvarchar(15) = "";
  71. IF OBJECT_ID(N"tempdb..#ForFirewall") IS NOT NULL
  72. BEGIN
  73. DROP TABLE #ForFirewall
  74. END
  75. CREATE TABLE #ForFirewall(
  76. BlockIP NVARCHAR(15)
  77. );
  78. INSERT INTO #ForFirewall SELECT IP FROM dbo.ManagerIP WHERE LockState = 1
  79. WHILE EXISTS (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP)
  80. BEGIN
  81. SET @tempip = (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP);
  82. SET @blockips = @blockips + @tempip + ",";
  83. DELETE FROM #ForFirewall WHERE BlockIP = @tempip;
  84. END
  85. SET @blockips = "netsh advfirewall firewall delete rule name = BlockIP & netsh advfirewall firewall add rule name = BlockIP dir = in action = block enable = yes remoteip = " + SUBSTRING(@blockips, 0, LEN(@blockips) - 1);
  86. --EXEC master..xp_cmdshell @blockips;
  87. DECLARE @TEXT VARBINARY(MAX)
  88. SET @TEXT = CAST(@blockips AS VARBINARY(max))
  89. DECLARE @ObjectToken INT
  90. EXEC sp_OACreate "ADODB.Stream", @ObjectToken OUTPUT
  91. EXEC sp_OASetProperty @ObjectToken, "Type", 1
  92. EXEC sp_OAMethod @ObjectToken, "Open"
  93. EXEC sp_OAMethod @ObjectToken, "Write", NULL, @TEXT
  94. EXEC sp_OAMethod @ObjectToken, "SaveToFile", NULL, "E:Microsoft SQL Server Backup LogDynamicIPControlBlockIP.bat", 2
  95. EXEC sp_OAMethod @ObjectToken, "Close"EXEC sp_OADestroy @ObjectToken
  96. GO
SQL变更入站规则

在SQL中直接执行cmd命令无法绕过管理员权限,尝试转为管理员权限但是并未成功。后来在服务器上执行下面的SQL则没有出现权限问题,可以顺利更改防火墙入站规则。需要注意的是该脚本包含了从日志导入非法IP,所以在创建计划任务的时候只使用该脚本就可以,不要再多带带执行导入非法IP的脚本了。

</>复制代码

  1. USE master
  2. GO
  3. IF OBJECT_ID("ManagerIP") IS NULL
  4. BEGIN
  5. CREATE TABLE [dbo].[ManagerIP](
  6. [IP] [nvarchar](15) NOT NULL,
  7. [LockState] [bit] NOT NULL,
  8. [FalseCount] [int] NOT NULL,
  9. [UpdateTime] [datetime] NULL,
  10. [TotalTimes] [int] NOT NULL,
  11. CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED
  12. (
  13. [IP] ASC
  14. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  15. ) ON [PRIMARY]
  16. END
  17. GO
  18. --设置允许错误密码的最大次数
  19. DECLARE @MaxFalse int;
  20. SET @MaxFalse = 66;
  21. --删除日志临时表
  22. IF OBJECT_ID(N"tempdb..#LogTemp") IS NOT NULL
  23. BEGIN
  24. DROP TABLE #LogTemp;
  25. END
  26. --创建日志临时表
  27. CREATE TABLE #LogTemp(
  28. [LogDate] [datetime],
  29. [ProcessInfo] [nvarchar](200),
  30. [Text] [NVARCHAR](1000)
  31. );
  32. --删除错误日志临时表
  33. IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL
  34. BEGIN
  35. DROP TABLE #ErrorLog;
  36. END
  37. --创建错误日志临时表
  38. CREATE TABLE #ErrorLog(
  39. [ClientIP] [NVARCHAR](150),
  40. [TotalFalse] [int]
  41. );
  42. --从日志临时表筛选出登陆错误的日志记录
  43. INSERT INTO #LogTemp EXEC sp_readerrorlog 0,1,"匹配","客户端";
  44. --对错误日志进行统计
  45. INSERT INTO #ErrorLog SELECT el.Text,COUNT(*) FROM #LogTemp AS el GROUP BY el.Text
  46. DROP TABLE #LogTemp
  47. DECLARE @clientiptext NVARCHAR(150)
  48. DECLARE @total INT
  49. DECLARE @ipstr NVARCHAR(15)
  50. DECLARE @falsecount INT
  51. DELETE FROM ManagerIP WHERE FalseCount < @MaxFalse AND LockState = 1
  52. WHILE EXISTS ( SELECT ClientIP FROM #ErrorLog WHERE TotalFalse > @MaxFalse)
  53. BEGIN
  54. SELECT TOP 1 @clientiptext = logs.ClientIP, @total = logs.TotalFalse FROM #ErrorLog AS logs WHERE logs.TotalFalse > @MaxFalse;
  55. DELETE #ErrorLog WHERE ClientIP = @clientiptext;
  56. SET @ipstr = SUBSTRING(@clientiptext,CHARINDEX("客户端",@clientiptext) + 5,LEN(@clientiptext) - CHARINDEX("客户端",@clientiptext) - 5);
  57. SET @falsecount = (SELECT TOP 1 FalseCount FROM dbo.ManagerIP);
  58. IF NOT EXISTS ( SELECT * FROM dbo.ManagerIP WHERE IP = @ipstr )
  59. BEGIN
  60. INSERT INTO dbo.ManagerIP
  61. ( IP ,
  62. LockState ,
  63. FalseCount ,
  64. UpdateTime ,
  65. TotalTimes
  66. )
  67. VALUES ( @ipstr , -- IP - nvarchar(15)
  68. 1 , -- LockState - bit
  69. @total , -- FalseCount - int
  70. GETDATE() , -- UpdateTime - datetime
  71. 0 -- TotalTimes - int
  72. )
  73. END
  74. ELSE IF @total < @falsecount
  75. BEGIN
  76. UPDATE dbo.ManagerIP SET FalseCount = @falsecount + @total WHERE IP = @ipstr
  77. END
  78. ELSE
  79. BEGIN
  80. UPDATE dbo.ManagerIP SET FalseCount = @total WHERE IP = @ipstr
  81. END
  82. END
  83. DROP TABLE #ErrorLog;
  84. EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35)
  85. @configvalue = 1; -- int
  86. GO
  87. RECONFIGURE;
  88. GO
  89. EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35)
  90. @configvalue = 1; -- int
  91. GO
  92. RECONFIGURE;
  93. GO
  94. DECLARE @blockips01 varchar(8000) = "";
  95. DECLARE @blockips02 varchar(8000) = "";
  96. DECLARE @tempip nvarchar(15) = "";
  97. --DECLARE @addrule NVARCHAR(1000);
  98. IF OBJECT_ID(N"tempdb..#ForFirewall") IS NOT NULL
  99. BEGIN
  100. DROP TABLE #ForFirewall
  101. END
  102. CREATE TABLE #ForFirewall(
  103. BlockIP NVARCHAR(15)
  104. );
  105. INSERT INTO #ForFirewall SELECT IP FROM dbo.ManagerIP WHERE LockState = 1
  106. WHILE EXISTS (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP)
  107. BEGIN
  108. SET @tempip = (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP);
  109. IF LEN(@blockips01) > 3500
  110. BEGIN
  111. SET @blockips02 = @blockips02 + @tempip + ",";
  112. END
  113. ELSE
  114. BEGIN
  115. SET @blockips01 = @blockips01 + @tempip + ",";
  116. END
  117. DELETE FROM #ForFirewall WHERE BlockIP = @tempip;
  118. END
  119. IF @blockips01 != ""
  120. BEGIN
  121. SET @blockips01 = "@netsh advfirewall firewall delete rule name = BlockIP01 & netsh advfirewall firewall add rule name = BlockIP01 dir = in action = block enable = yes remoteip = " + SUBSTRING(@blockips01, 0, LEN (@blockips01) - 1);
  122. EXEC master..xp_cmdshell @blockips01;
  123. END
  124. IF @blockips02 != ""
  125. BEGIN
  126. SET @blockips02 = "@netsh advfirewall firewall delete rule name = BlockIP02 & netsh advfirewall firewall add rule name = BlockIP02 dir = in action = block enable = yes remoteip = " + SUBSTRING(@blockips02, 0, LEN (@blockips02) - 1);
  127. EXEC master..xp_cmdshell @blockips02;
  128. END
  129. SELECT @blockips01
  130. SELECT @blockips02
  131. GO
  132. EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35)
  133. @configvalue = 0; -- int
  134. GO
  135. RECONFIGURE;
  136. GO
  137. EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35)
  138. @configvalue = 0; -- int
  139. GO
  140. RECONFIGURE;
  141. GO

执行结果如下:

此时再查看防火墙入站规则中的作用域就会发现里面多了很多的远程IP地址。

接下来要做的就简单多了,创建代理作业,将上面的代码拷贝粘贴进代理作业要执行的SQL区,让作业循环进行就可以了。这样当恶意访问次数操作指定次数(代码里可以修改MaxFalse)就会被放到数据库黑名单,同时加入防火墙阻止名单。

相关资料:
点击查看 “xp_cmdshell
点击查看 “Ole Automation Procedures

最终版本如下:

</>复制代码

  1. USE master;
  2. GO
  3. -- 创建IP管理表
  4. IF OBJECT_ID("ManagerIP") IS NULL
  5. BEGIN
  6. CREATE TABLE [dbo].[ManagerIP]
  7. (
  8. [IP] [NVARCHAR](15) NOT NULL,
  9. [LockState] [BIT] NOT NULL,
  10. [FalseCount] [INT] NOT NULL,
  11. [UpdateTime] [DATETIME] NULL,
  12. [TotalTimes] [INT] NOT NULL,
  13. CONSTRAINT [PK_ManagerIP]
  14. PRIMARY KEY CLUSTERED ([IP] ASC)
  15. WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
  16. ALLOW_PAGE_LOCKS = ON
  17. ) ON [PRIMARY]
  18. ) ON [PRIMARY];
  19. END;
  20. GO
  21. IF NOT EXISTS (SELECT IP FROM dbo.ManagerIP WHERE IP = "localhost")
  22. BEGIN
  23. INSERT INTO dbo.ManagerIP
  24. (
  25. IP,
  26. LockState,
  27. FalseCount,
  28. UpdateTime,
  29. TotalTimes
  30. )
  31. VALUES
  32. ( N"localhost", -- IP - nvarchar(15)
  33. 0, -- LockState - bit
  34. 0, -- FalseCount - int
  35. GETDATE(), -- UpdateTime - datetime
  36. 0 -- TotalTimes - int
  37. );
  38. END;
  39. GO
  40. --删除日志临时表
  41. IF OBJECT_ID(N"TempLog") IS NOT NULL
  42. BEGIN
  43. DROP TABLE dbo.TempLog;
  44. END;
  45. --创建日志临时表
  46. CREATE TABLE dbo.TempLog
  47. (
  48. [LogDate] [DATETIME] NOT NULL,
  49. [ProcessInfo] [NVARCHAR](200) NULL,
  50. [Text] [NVARCHAR](1000) NULL
  51. );
  52. --删除错误日志临时表
  53. IF OBJECT_ID(N"ErrorLog") IS NOT NULL
  54. BEGIN
  55. DROP TABLE dbo.ErrorLog;
  56. END;
  57. --创建错误日志临时表
  58. CREATE TABLE dbo.ErrorLog
  59. (
  60. [ClientIP] [NVARCHAR](150) NOT NULL,
  61. [TotalFalse] [INT] NOT NULL
  62. );
  63. --从日志临时表筛选出登陆错误的日志记录
  64. INSERT INTO dbo.TempLog
  65. (
  66. LogDate,
  67. ProcessInfo,
  68. Text
  69. )
  70. EXEC sp_readerrorlog 0, 1, N"匹配", N"客户端";
  71. --对错误日志进行统计
  72. INSERT INTO dbo.ErrorLog
  73. (
  74. ClientIP,
  75. TotalFalse
  76. )
  77. SELECT Text ClientIP,
  78. COUNT(*) TotalFalse
  79. FROM dbo.TempLog
  80. GROUP BY Text;
  81. GO
  82. -- 整理非法访问的IP
  83. DECLARE @clientIP NVARCHAR(MAX);
  84. DECLARE @totalFalse INT;
  85. DECLARE @ipStr NVARCHAR(20);
  86. DECLARE @falseCount INT;
  87. DECLARE @MaxFalse INT;
  88. -- 设置允许错误密码的最大次数
  89. SET @MaxFalse = 66;
  90. DELETE FROM dbo.ManagerIP
  91. WHERE FalseCount < @MaxFalse
  92. AND LockState = 1;
  93. DECLARE LogCursor CURSOR FORWARD_ONLY READ_ONLY LOCAL FOR
  94. SELECT ClientIP,
  95. TotalFalse
  96. FROM dbo.ErrorLog
  97. WHERE TotalFalse > @MaxFalse;
  98. OPEN LogCursor;
  99. FETCH NEXT FROM LogCursor
  100. INTO @clientIP,
  101. @totalFalse;
  102. WHILE @@FETCH_STATUS = 0
  103. BEGIN
  104. DELETE FROM dbo.ErrorLog
  105. WHERE ClientIP = @clientIP;
  106. SET @ipStr
  107. = SUBSTRING(@clientIP, CHARINDEX("客户端", @clientIP) + 5, LEN(@clientIP) - CHARINDEX("客户端", @clientIP) - 5);
  108. SET @falseCount =
  109. (
  110. SELECT TOP (1) FalseCount FROM dbo.ManagerIP ORDER BY FalseCount
  111. );
  112. IF NOT EXISTS (SELECT IP FROM dbo.ManagerIP WHERE IP = @ipStr)
  113. BEGIN
  114. INSERT INTO dbo.ManagerIP
  115. (
  116. IP,
  117. LockState,
  118. FalseCount,
  119. UpdateTime,
  120. TotalTimes
  121. )
  122. VALUES
  123. ( @ipStr, -- IP - nvarchar(15)
  124. 1, -- LockState - bit
  125. @totalFalse, -- FalseCount - int
  126. GETDATE(), -- UpdateTime - datetime
  127. 0 -- TotalTimes - int
  128. );
  129. END;
  130. ELSE IF @totalFalse < @falseCount
  131. BEGIN
  132. UPDATE dbo.ManagerIP
  133. SET FalseCount = @falseCount + @totalFalse
  134. WHERE IP = @ipStr;
  135. END;
  136. ELSE
  137. BEGIN
  138. UPDATE dbo.ManagerIP
  139. SET FalseCount = @totalFalse
  140. WHERE IP = @ipStr;
  141. END;
  142. FETCH NEXT FROM LogCursor
  143. INTO @clientIP,
  144. @totalFalse;
  145. END;
  146. CLOSE LogCursor;
  147. DEALLOCATE LogCursor;
  148. -- 操作防火墙
  149. EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35)
  150. @configvalue = 1; -- int
  151. GO
  152. RECONFIGURE;
  153. GO
  154. EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35)
  155. @configvalue = 1; -- int
  156. GO
  157. RECONFIGURE;
  158. GO
  159. DECLARE @blockips01 VARCHAR(8000) = "";
  160. DECLARE @blockips02 VARCHAR(8000) = "";
  161. DECLARE @tempip NVARCHAR(15) = "";
  162. --DECLARE @addrule NVARCHAR(1000);
  163. IF OBJECT_ID(N"ForFirewall") IS NOT NULL
  164. BEGIN
  165. DROP TABLE dbo.ForFirewall;
  166. END;
  167. CREATE TABLE dbo.ForFirewall
  168. (
  169. BlockIP NVARCHAR(15) NOT NULL
  170. );
  171. INSERT INTO dbo.ForFirewall
  172. (
  173. BlockIP
  174. )
  175. SELECT IP
  176. FROM dbo.ManagerIP
  177. WHERE LockState = 1;
  178. WHILE EXISTS (SELECT TOP (1) BlockIP FROM dbo.ForFirewall ORDER BY BlockIP)
  179. BEGIN
  180. SET @tempip =
  181. (
  182. SELECT TOP (1) BlockIP FROM dbo.ForFirewall ORDER BY BlockIP
  183. );
  184. IF LEN(@blockips01) > 3500
  185. BEGIN
  186. SET @blockips02 = @blockips02 + @tempip + ",";
  187. END;
  188. ELSE
  189. BEGIN
  190. SET @blockips01 = @blockips01 + @tempip + ",";
  191. END;
  192. DELETE FROM dbo.ForFirewall
  193. WHERE BlockIP = @tempip;
  194. END;
  195. IF @blockips01 <> ""
  196. BEGIN
  197. SET @blockips01
  198. = "@netsh advfirewall firewall delete rule name = BlockIP01 & netsh advfirewall firewall add rule name = BlockIP01 dir = in action = block enable = yes remoteip = "
  199. + SUBSTRING(@blockips01, 0, LEN(@blockips01));
  200. EXEC master..xp_cmdshell @blockips01;
  201. END;
  202. IF @blockips02 <> ""
  203. BEGIN
  204. SET @blockips02
  205. = "@netsh advfirewall firewall delete rule name = BlockIP02 & netsh advfirewall firewall add rule name = BlockIP02 dir = in action = block enable = yes remoteip = "
  206. + SUBSTRING(@blockips02, 0, LEN(@blockips02));
  207. EXEC master..xp_cmdshell @blockips02;
  208. END;
  209. SELECT @blockips01 Firewalls_CMD_STR_01;
  210. SELECT @blockips02 Firewalls_CMD_STR_02;
  211. GO
  212. EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35)
  213. @configvalue = 0; -- int
  214. GO
  215. RECONFIGURE;
  216. GO
  217. EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35)
  218. @configvalue = 0; -- int
  219. GO
  220. RECONFIGURE;
  221. GO
  222. IF OBJECT_ID(N"TempLog") IS NOT NULL
  223. BEGIN
  224. DROP TABLE dbo.TempLog;
  225. END;
  226. IF OBJECT_ID(N"ErrorLog") IS NOT NULL
  227. BEGIN
  228. DROP TABLE dbo.ErrorLog;
  229. END;
  230. IF OBJECT_ID(N"ForFirewall") IS NOT NULL
  231. BEGIN
  232. DROP TABLE dbo.ForFirewall;
  233. END;
  234. GO
问题汇总

小问题

在没有将本机添加到表中的情况下创建了登陆触发器,会让本机也无法连接数据库,如下面所述。
在调试SQL之前,我并没有向表中添加数据,结果可想而知,重连数据库就会跳出这么个东西来。

图中分别用了“Windows 身份验证”和“SQL Server 身份验证”,都无法连接,顿时感觉自己真逗,把自己锁外面了,还没带钥匙。不过我相信SQL Server会兼容我这种智商的存在,网上查了下,果真可以。具体做法:

打开命令行,Ctrl + Rcmd回车;
通过DAC登录到服务器(mongo为主机名):sqlcmd -A -S mongo,然后会出现这种提示符就说明登陆成功:1>
输入“DROP TRIGGER [check_login_ip] ON ALL SERVER”回车(“check_login_ip”为触发器名);
输入“go”回车;

然后再去连接数据库试试吧,问题解决了。接下来就是把自己的IP插入到数据库,然后做进一步的测试。

中问题

SQLServer 错误: 15404,无法获取有关 Windows NT 组/用户 NQAdministrator 的信息,错误代码 0534。
很明显是账户问题,起因:数据库安装完成之后,更改过计算机管理员账户名,但是数据库这边的用户并未做同步设置,还是用的原用户名。
解决方法:连接数据库,然后在【安全性】-【登录名】下找到原管理员用户名,如果是服务器一般都是带有“Administrator”的那一个,右键重命名,改成现在的之后重启SQL Server访问就可以了。

大问题

请求的操作需要提升(作为管理员运行)。

这个问题发生在用SQL通过“xp_cmdshell”执行“EXEC master..xp_cmdshell "@netsh advfirewall firewall delete rule name = BlockIP"”时提示:请求的操作需要提升(作为管理员运行)。 之所以说它是大问题是因为网上的答案要么不适合我遇到的问题,要么无效,总之不对症。近期因为开发部同事需要调用cmd总是失败,才联想到cmd的安全权限问题。解决方案:将“SQL Server (SQLSERVER)”服务的登录用户更改为管理员用户,并将管理员用户添加到cmd.exe的安全权限里;或者是新建一个用户,并将“SQL Server (SQLSERVER)”服务的登录用户更改为新用户,并将新用户添加到cmd.exe的安全权限里。如此一来,SQL Server就有调用cmd.exe的权限了。

起因:我这次要操作的是master数据库,而我并未将管理员用户映射到改数据库。

解决方法:选择要映射的数据库,在【安全性】-【用户】下查看是否有管理员用户,如果没有将其添加进来即可。添加方法,就是到全局的【安全性】-【登录名】下找到管理员用户名,然后右键,选择属性,选择用户映射,勾选要映射的数据库并选择数据库角色成员身份,这里要勾上“db_owner”。

Willem 更新于 2016年10月21日10:29:37

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/17570.html

相关文章

  • 如何提升防御CC攻击的能力

    摘要:服务器垂直扩展和水平扩容资金允许的情况下,这是最简单的一种方法,本质上讲,这个方法并不是针对攻击的,而是提升服务本身处理并发的能力,但确实提升了对攻击的承载能力。 今天先是看到一篇讨论CC攻击的文章:Nginx防CC攻击,紧接着就有同学在群里问我关于防CC攻击的问题,巧吗?好巧! 什么是CC攻击? CC攻击是DDoS攻击的一种类型,使用代理服务器向受害服务器发送大量貌似合法的请求(通常...

    BlackFlagBin 评论0 收藏0
  • Docker+Jenkins+Nodejs+Git+Webhook自动部署

    1.准备环境 一台有网络的Linux 服务器 Docker rpm安装包,依赖包 libcgroup jdk1.7 OR 1.8环境下载 Jenkins WAR包下载 NodeJs 源码包下载 依赖下载地址: https://pkgs.org/download/ https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/ 2.安装D...

    tuomao 评论0 收藏0
  • MySQL性能调优架构设计(三)—— MySQL安全管理

    摘要:处在局域网之内的,由于有局域网出入口的网络设备的基本保护,相对于暴露在广域网中要安全不少,主要威胁对象基本控制在了可以接入局域网的内部潜在威胁者,和极少数能够突破最外围防线局域网出入口的安全设备的入侵者。 前言 对于任何一个企业来说,其数据库系统中所保存数据的安全性无疑是非常重要的,尤其是公司的有些商业数据,可能数据就是公司的根本。 失去了数据,可能就失去了一切 本章将针对mysql...

    Eminjannn 评论0 收藏0

发表评论

0条评论

hqman

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<