摘要:腳本功能說明自動刪除重名數據庫,然后創建自動創建登陸管理表自動刪除重名的登陸觸發器,然后重新創建。如果身份驗證失敗,將不激發登錄觸發器。如果由其他例程調用即使這些例程由或登錄觸發器進行調用,將返回。
查看數據庫日志發現好多非法登陸失敗的記錄,雖然之前已經更改了服務器和數據庫的管理員賬戶的用戶名,但是為了保險起見,還是再加上一道措施。創建登錄觸發器,只允許指定的IP訪問,服務器設置白名單,但是這只適用于訪問用戶的IP固定不會經常變更的情況。而我們的開發服務器卻不符合這種情況,只能想辦法實施一個動態的管理方案。
聲明:本文為Willem(Mongo)原創,轉載請注明原文鏈接:https://segmentfault.com/a/11...。
為節省您的寶貴時間,請直接看觸發器2.0 + SQL變更入站規則即可,有問題可先參照問題匯總。如有其他問題請在評論中留言,一起探討。謝謝!
網上有文章(點擊查看) 寫的很詳細,這里就不贅述了。下面的SQL是創建數據庫觸發器時給的默認模板,根據自己的情況進行修改:
--==================================== -- Create database trigger template --==================================== USE登陸觸發器的創建腳本 v1.0GO IF EXISTS( SELECT * FROM sys.triggers WHERE name = N" " AND parent_class_desc = N"DATABASE" ) DROP TRIGGER ON DATABASE GO CREATE TRIGGER ON DATABASE FOR AS IF IS_MEMBER ("db_owner") = 0 BEGIN PRINT "You must ask your DBA to drop or alter tables!" ROLLBACK TRANSACTION END GO
下面這個腳本只能DBA自己先向IP管理表插入允許訪問數據庫的IP,因為登陸觸發器只有身份驗證通過時才能觸發,所以暫時沒去記錄非法登陸失敗的IP:
/**登錄觸發器將在登錄的身份驗證階段完成之后且用戶會話實際建立之前激發。如果身份驗證失敗,將不激發登錄觸發器。**/ USE [master] GO /****** Object: Table [dbo].[ManagerIP] Script Date: 2016年10月13日11:31:22 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO --將數據庫回滾到原始配置狀態,然后刪除 IF DB_ID("LoginIP") IS NOT NULL ALTER DATABASE LoginIP SET SINGLE_USER WITH ROLLBACK IMMEDIATE DROP DATABASE LoginIP GO --創建數據庫 CREATE DATABASE [LoginIP] GO USE [LoginIP] GO --創建IP管理表 CREATE TABLE [dbo].[ManagerIP]( [IP] [nvarchar](15) NOT NULL, [BlockState] [bit] NOT NULL, [FalseCount] [int] NOT NULL, [UpdateTime] [datetime] NULL, [TotalTimes] [int] NOT NULL, CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED ( [IP] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO --插入允許通過的IP INSERT INTO dbo.ManagerIP ( IP , BlockState , FalseCount , UpdateTime , TotalTimes ) VALUES ( N"" , -- IP - nvarchar(15) 0 , -- BlockState - bit 0 , -- FalseCount - int GETDATE() , -- UpdateTime - datetime 0 -- TotalTimes - int ) INSERT INTO dbo.ManagerIP ( IP , BlockState , FalseCount , UpdateTime , TotalTimes ) VALUES ( N"221.227.108.132" , -- IP - nvarchar(15) 0 , -- BlockState - bit 0 , -- FalseCount - int GETDATE() , -- UpdateTime - datetime 0 -- TotalTimes - int ) GO USE master GO --刪除觸發器(注意:登陸觸發器是存放在sys.server_triggers ,而不是sys.triggers) IF EXISTS(SELECT * FROM sys.server_triggers WHERE name = "check_login_ip") --AND parent_class_desc = N"LoginIP") DROP TRIGGER check_login_ip ON ALL SERVER GO --創建觸發器 --CREATE TRIGGER trigger_name ON LoginIP CREATE TRIGGER check_login_ip ON ALL SERVER FOR LOGON AS IF IS_SRVROLEMEMBER ("sysadmin") = 1 BEGIN DECLARE @ip NVARCHAR(15); --只有直接在 DDL 或登錄觸發器內部引用 EVENTDATA 時,EVENTDATA 才會返回數據。 如果 EVENTDATA 由其他例程調用(即使這些例程由 DDL 或登錄觸發器進行調用),將返回 NULL。 SET @ip = (SELECT EVENTDATA().value("(/EVENT_INSTANCE/ClientHost)[1]","NVARCHAR(15)")); IF NOT EXISTS(SELECT IP FROM [LoginIP].[dbo].[ManagerIP] WHERE IP = @ip) ROLLBACK TRANSACTION; END GO
相關鏈接:
點擊查看關于“EVENTDATA() ”的說明;
點擊查看“Sql Server中判斷表或者數據庫是否存在 ”
點擊查看“IS_SRVROLEMEMBER("sysadmin") ”的詳細說明
點擊查看“登錄觸發器”的詳細說明
點擊查看“sys.server_triggers”的詳細說明
點擊查看“sys.triggers”的詳細說明
上述腳本復制到SQL Server直接執行就可以。
腳本功能說明:自動刪除重名數據庫,然后創建;自動創建登陸IP管理表;自動刪除重名的登陸觸發器,然后重新創建。
上面提到了關于允許訪問數據庫的IP的管理問題,1.0 版本只能手動操作,而不能動態的自行管理IP,這樣就造成了不夠靈活的問題。
問題產生的情景:
如果我在表中添加了家里和公司的IP,光是這就很麻煩,因為要去統計開發人員家中的IP地址,更何況一旦到客戶現場演示時,IP又無法添加,只能讓已添加的IP進入數據庫手動添加,實在有些麻煩。但是又不得不去設置,因為查看一下數據庫記錄就不難看到,每天都會有很多外界的IP來光顧,雖然還未成功,但難保哪天被黑了。
需求:來訪IP記入IP管理表,連續登陸失敗超過設定的次數就將該IP設置為黑名單,可以防止其暴力破解數據庫密碼。如果未超過設定次數登陸成功,則將失敗次數清0。聽起來跟輸入銀行密碼的感覺差不多。下面是最終的邏輯圖:
又經過了一天半的時間,產生了下面最終的腳本,可以動態控制IP,這里的動態是相對前面的靜態而言;
/**登錄觸發器將在登錄的身份驗證階段完成之后且用戶會話實際建立之前激發。如果身份驗證失敗,將不激發登錄觸發器。**/ USE [master] GO /****** Object: Table [dbo].[ManagerIP] Script Date: 2016年10月13日11:31:22 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO --創建IP管理表 IF OBJECT_ID (N"dbo.ManagerIP", N"U") IS NULL BEGIN CREATE TABLE [dbo].[ManagerIP]( [IP] [nvarchar](15) NOT NULL, [LockState] [bit] NOT NULL, [FalseCount] [int] NOT NULL, [UpdateTime] [datetime] NULL, [TotalTimes] [int] NOT NULL, CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED ( [IP] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]; END GO --插入允許通過的IP IF (SELECT COUNT(*) FROM dbo.ManagerIP) = 0 BEGIN INSERT INTO dbo.ManagerIP ( IP , LockState , FalseCount , UpdateTime , TotalTimes ) VALUES ( N"" , -- IP - nvarchar(15) 0 , -- BlockState - bit 0 , -- FalseCount - int GETDATE() , -- UpdateTime - datetime 0 -- TotalTimes - int ); END GO --刪除觸發器(注意:登陸觸發器是存放在sys.server_triggers ,而不是sys.triggers) IF EXISTS(SELECT * FROM sys.server_triggers WHERE name = "check_login_ip") BEGIN DROP TRIGGER check_login_ip ON ALL SERVER END GO --創建觸發器 --CREATE TRIGGER trigger_name ON LoginIP CREATE TRIGGER check_login_ip ON ALL SERVER FOR LOGON AS IF IS_SRVROLEMEMBER ("sysadmin") = 1 BEGIN DECLARE @ip NVARCHAR(15); --只有直接在 DDL 或登錄觸發器內部引用 EVENTDATA 時,EVENTDATA 才會返回數據。 如果 EVENTDATA 由其他例程調用(即使這些例程由 DDL 或登錄觸發器進行調用),將返回 NULL。 SET @ip = (SELECT EVENTDATA().value("(/EVENT_INSTANCE/ClientHost)[1]","NVARCHAR(15)")); IF (SELECT COUNT(*) FROM [master].[dbo].[ManagerIP] WHERE IP = @ip AND LockState = 1) > 0 BEGIN ROLLBACK; END ELSE IF (SELECT COUNT(*) FROM [master].[dbo].[ManagerIP] WHERE IP = @ip AND LockState = 0) > 0 BEGIN UPDATE [master].[dbo].[ManagerIP] SET UpdateTime = GETDATE() WHERE IP = @ip; SET NOEXEC ON; END --刪除臨時表 ELSE IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL BEGIN DROP TABLE #ErrorLog; END --創建臨時表 CREATE TABLE #ErrorLog( [LogDate] [datetime], [ProcessInfo] [nvarchar](200), [Text] [NVARCHAR](1000) ); --讀取當前日志插入到臨時表 INSERT INTO #ErrorLog EXEC sp_readerrorlog 0,1,"匹配",@ip; -- @p1 = 0, -- int 0為當前日志,1-9為對應編號日志 -- @p2 = 1, -- int 1為服務器日志,2為代理日志 -- @p3 = N"", -- nvarchar(4000) 包含的第一個字段 -- @p4 = N"" -- nvarchar(4000) 包含的第二個字段 DECLARE @TotalFalse int SET @TotalFalse = (SELECT COUNT(*) FROM #ErrorLog); IF @TotalFalse < 5 BEGIN INSERT INTO [dbo].[ManagerIP] ([IP], [LockState], [FalseCount], [UpdateTime], [TotalTimes]) VALUES (@ip, 0, 0, GETDATE(), 0); SET NOEXEC ON; END ELSE BEGIN INSERT INTO [dbo].[ManagerIP] ([IP], [LockState], [FalseCount], [UpdateTime], [TotalTimes]) VALUES (@ip, 1, 0, GETDATE(), 0); END END GO
參考資料:
點擊查看“捕獲登錄觸發器事件數據”;
點擊查看“GETDATE”;
點擊查看“OBJECT_ID”;
SQL如下:
USE master GO --設置允許錯誤密碼的最大次數 DECLARE @MaxFalse int; SET @MaxFalse = 10; --刪除日志臨時表 IF OBJECT_ID(N"tempdb..#LogTemp") IS NOT NULL BEGIN DROP TABLE #LogTemp; END --創建日志臨時表 CREATE TABLE #LogTemp( [LogDate] [datetime], [ProcessInfo] [nvarchar](200), [Text] [NVARCHAR](1000) ); --刪除錯誤日志臨時表 IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL BEGIN DROP TABLE #ErrorLog; END --創建錯誤日志臨時表 CREATE TABLE #ErrorLog( [ClientIP] [NVARCHAR](150), [TotalFalse] [int] ); --從日志臨時表篩選出登陸錯誤的日志記錄 INSERT INTO #LogTemp EXEC sp_readerrorlog 0,1,"匹配","客戶端"; --對錯誤日志進行統計 INSERT INTO #ErrorLog SELECT el.Text,COUNT(*) FROM #LogTemp AS el GROUP BY el.Text DROP TABLE #LogTemp DECLARE @clientiptext nvarchar(150) DECLARE @total INT DECLARE @ipstr nvarchar(15) WHILE EXISTS ( SELECT ClientIP FROM #ErrorLog WHERE TotalFalse > @MaxFalse) BEGIN SELECT TOP 1 @clientiptext = logs.ClientIP, @total = logs.TotalFalse FROM #ErrorLog AS logs WHERE logs.TotalFalse > @MaxFalse; DELETE #ErrorLog WHERE ClientIP = @clientiptext; SET @ipstr = SUBSTRING(@clientiptext,CHARINDEX("客戶端",@clientiptext) + 5,LEN(@clientiptext) - CHARINDEX("客戶端",@clientiptext) - 5); IF NOT EXISTS ( SELECT * FROM dbo.ManagerIP WHERE IP = @ipstr ) BEGIN INSERT INTO dbo.ManagerIP ( IP , LockState , FalseCount , UpdateTime , TotalTimes ) VALUES ( @ipstr , -- IP - nvarchar(15) 1 , -- LockState - bit @total , -- FalseCount - int GETDATE() , -- UpdateTime - datetime 0 -- TotalTimes - int ) END ELSE IF @total < (SELECT FalseCount FROM dbo.ManagerIP) BEGIN UPDATE dbo.ManagerIP SET FalseCount += @total WHERE IP = @ipstr END ELSE BEGIN UPDATE dbo.ManagerIP SET FalseCount = @total WHERE IP = @ipstr END END DROP TABLE #ErrorLog GO依然存在的問題
這樣看起來是沒問題了,但是這樣做并沒能防止其他人暴力破解密碼,只是破解之后不能通過該IP訪問數據庫而已,原因之前也提到了,登錄觸發器只能在驗證通過后才能激活,反應到實際操作中就是通過驗證和未通過驗證的提示是不同的,只要發現問題提示發生的變化就可以根據這個來判斷賬戶和密碼是否正確,當然最好的做法就是不要對外開放數據庫。不過這樣做就會讓開發人員麻煩些。現在的問題就是如何可以將定為非法的IP阻止在驗證之前。這里想到的一個做法是將該IP放到防火墻阻止列表中,這樣的話無法通過防火墻,那么就不會訪問數據庫,也就不會進行驗證了。
因為前面的操作都配合觸發器、計劃任務或者維護計劃進行了自動化,所以這樣也要做到自動向防火墻中添加IP,這樣就需要腳本來進行操作了。而可以操作防火墻的指令: C:Windowssystem32>netsh advfirewall firewall add rule ? 用法: add rule name=dir=in|out action=allow|block|bypass [program= ] [service= |any] [description= ] [enable=yes|no (default=yes)] [profile=public|private|domain|any[,...]] [localip=any| | | | | ] [remoteip=any|localsubnet|dns|dhcp|wins|defaultgateway|
| | | | ] [localport=0-65535|
[,...]|RPC|RPC-EPMap|IPHTTPS|any (default=any)] [remoteport=0-65535| [,...]|any (default=any)] [protocol=0-255|icmpv4|icmpv6|icmpv4:type,code|icmpv6:type,code| tcp|udp|any (default=any)] [interfacetype=wireless|lan|ras|any] [rmtcomputergrp= ] [rmtusrgrp= ] [edge=yes|deferapp|deferuser|no (default=no)] [security=authenticate|authenc|authdynenc|authnoencap|notrequired (default=notrequired)] 備注: - 將新的入站或出站規則添加到防火墻策略。 - 規則名稱應該是唯一的,且不能為 "all"。 - 如果已指定遠程計算機或用戶組,則 security 必須為 authenticate、authenc、authdynenc 或 authnoencap。 - 為 authdynenc 設置安全性可允許系統動態協商為匹配 給定 Windows 防火墻規則的通信使用加密。 根據現有連接安全規則屬性協商加密。選擇此選項后,只要入站 IPSec 連接已設置安全保護, 但未使用 IPSec 進行加密,計算機就能夠接收該入站連接的第一個 TCP 或 UDP 包。一旦處理了第一個數據包,服務器將重新協商連接并對其進行升級,以便所 有后續通信都完全加密。 - 如果 action=bypass,則 dir=in 時必須指定遠程計算機組。 - 如果 service=any,則規則僅應用到服務。 - ICMP 類型或代碼可以為 "any"。 - Edge 只能為入站規則指定。 - AuthEnc 和 authnoencap 不能同時使用。 - Authdynenc 僅當 dir=in 時有效。 - 設置 authnoencap 后,security=authenticate 選項就變成可選參數。 示例: 為不具有封裝的 messenger.exe 添加入站規則: netsh advfirewall firewall add rule name="allow messenger" dir=in program="c:programfilesmessengermsmsgs.exe" security=authnoencap action=allow 為端口 80 添加出站規則: netsh advfirewall firewall add rule name="allow80" protocol=TCP dir=out localport=80 action=block 為 TCP 端口 80 通信添加需要安全和加密的入站規則: netsh advfirewall firewall add rule name="Require Encryption for Inbound TCP/80" protocol=TCP dir=in localport=80 security=authdynenc action=allow 為 messenger.exe 添加需要安全的入站規則: netsh advfirewall firewall add rule name="allow messenger" dir=in program="c:program filesmessengermsmsgs.exe" security=authenticate action=allow 為 SDDL 字符串標識的組 acmedomainscanners 添加經過身份驗證的防火墻跳過規則: netsh advfirewall firewall add rule name="allow scanners" dir=in rmtcomputergrp= action=bypass security=authenticate 為 udp- 的本地端口 5000-5010 添加出站允許規則 Add rule name="Allow port range" dir=out protocol=udp localport=5000-5010 action=allow
通過幫助信息,我們可以了解到其中各個參數的含義及用途。而我們所需要達到的目的是:防止某IP訪問該服務器上的數據庫。對照上面翻譯成簡單的腳本就是:
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文件中可以正常執行,但是直接執行該文件則有問題。不推薦此種方法,請查看下一種方法。
USE master GO --設置允許錯誤密碼的最大次數 DECLARE @MaxFalse int; SET @MaxFalse = 66; --刪除日志臨時表 IF OBJECT_ID(N"tempdb..#LogTemp") IS NOT NULL BEGIN DROP TABLE #LogTemp; END --創建日志臨時表 CREATE TABLE #LogTemp( [LogDate] [datetime], [ProcessInfo] [nvarchar](200), [Text] [NVARCHAR](1000) ); --刪除錯誤日志臨時表 IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL BEGIN DROP TABLE #ErrorLog; END --創建錯誤日志臨時表 CREATE TABLE #ErrorLog( [ClientIP] [NVARCHAR](150), [TotalFalse] [int] ); --從日志臨時表篩選出登陸錯誤的日志記錄 INSERT INTO #LogTemp EXEC sp_readerrorlog 0,1,"匹配","客戶端"; --對錯誤日志進行統計 INSERT INTO #ErrorLog SELECT el.Text,COUNT(*) FROM #LogTemp AS el GROUP BY el.Text DROP TABLE #LogTemp DECLARE @clientiptext nvarchar(150) DECLARE @total int DECLARE @ipstr nvarchar(15) DELETE FROM ManagerIP WHERE FalseCount < @MaxFalse AND LockState = 1 WHILE EXISTS ( SELECT ClientIP FROM #ErrorLog WHERE TotalFalse > @MaxFalse) BEGIN SELECT TOP 1 @clientiptext = logs.ClientIP, @total = logs.TotalFalse FROM #ErrorLog AS logs WHERE logs.TotalFalse > @MaxFalse; DELETE #ErrorLog WHERE ClientIP = @clientiptext; SET @ipstr = SUBSTRING(@clientiptext,CHARINDEX("客戶端",@clientiptext) + 5,LEN(@clientiptext) - CHARINDEX("客戶端",@clientiptext) - 5); IF NOT EXISTS ( SELECT * FROM dbo.ManagerIP WHERE IP = @ipstr ) BEGIN INSERT INTO dbo.ManagerIP ( IP , LockState , FalseCount , UpdateTime , TotalTimes ) VALUES ( @ipstr , -- IP - nvarchar(15) 1 , -- LockState - bit @total , -- FalseCount - int GETDATE() , -- UpdateTime - datetime 0 -- TotalTimes - int ) END END DROP TABLE #ErrorLog; EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35) @configvalue = 1; -- int GO RECONFIGURE; GO EXEC sys.sp_configure @configname = "Ole Automation Procedures", -- varchar(35) @configvalue = 1; -- int GO RECONFIGURE; GO DECLARE @blockips nvarchar(MAX) = ""; DECLARE @tempip nvarchar(15) = ""; IF OBJECT_ID(N"tempdb..#ForFirewall") IS NOT NULL BEGIN DROP TABLE #ForFirewall END CREATE TABLE #ForFirewall( BlockIP NVARCHAR(15) ); INSERT INTO #ForFirewall SELECT IP FROM dbo.ManagerIP WHERE LockState = 1 WHILE EXISTS (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP) BEGIN SET @tempip = (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP); SET @blockips = @blockips + @tempip + ","; DELETE FROM #ForFirewall WHERE BlockIP = @tempip; END 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); --EXEC master..xp_cmdshell @blockips; DECLARE @TEXT VARBINARY(MAX) SET @TEXT = CAST(@blockips AS VARBINARY(max)) DECLARE @ObjectToken INT EXEC sp_OACreate "ADODB.Stream", @ObjectToken OUTPUT EXEC sp_OASetProperty @ObjectToken, "Type", 1 EXEC sp_OAMethod @ObjectToken, "Open" EXEC sp_OAMethod @ObjectToken, "Write", NULL, @TEXT EXEC sp_OAMethod @ObjectToken, "SaveToFile", NULL, "E:Microsoft SQL Server Backup LogDynamicIPControlBlockIP.bat", 2 EXEC sp_OAMethod @ObjectToken, "Close"EXEC sp_OADestroy @ObjectToken GOSQL變更入站規則
在SQL中直接執行cmd命令無法繞過管理員權限,嘗試轉為管理員權限但是并未成功。后來在服務器上執行下面的SQL則沒有出現權限問題,可以順利更改防火墻入站規則。需要注意的是該腳本包含了從日志導入非法IP,所以在創建計劃任務的時候只使用該腳本就可以,不要再多帶帶執行導入非法IP的腳本了。
USE master GO IF OBJECT_ID("ManagerIP") IS NULL BEGIN CREATE TABLE [dbo].[ManagerIP]( [IP] [nvarchar](15) NOT NULL, [LockState] [bit] NOT NULL, [FalseCount] [int] NOT NULL, [UpdateTime] [datetime] NULL, [TotalTimes] [int] NOT NULL, CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED ( [IP] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] END GO --設置允許錯誤密碼的最大次數 DECLARE @MaxFalse int; SET @MaxFalse = 66; --刪除日志臨時表 IF OBJECT_ID(N"tempdb..#LogTemp") IS NOT NULL BEGIN DROP TABLE #LogTemp; END --創建日志臨時表 CREATE TABLE #LogTemp( [LogDate] [datetime], [ProcessInfo] [nvarchar](200), [Text] [NVARCHAR](1000) ); --刪除錯誤日志臨時表 IF OBJECT_ID(N"tempdb..#ErrorLog") IS NOT NULL BEGIN DROP TABLE #ErrorLog; END --創建錯誤日志臨時表 CREATE TABLE #ErrorLog( [ClientIP] [NVARCHAR](150), [TotalFalse] [int] ); --從日志臨時表篩選出登陸錯誤的日志記錄 INSERT INTO #LogTemp EXEC sp_readerrorlog 0,1,"匹配","客戶端"; --對錯誤日志進行統計 INSERT INTO #ErrorLog SELECT el.Text,COUNT(*) FROM #LogTemp AS el GROUP BY el.Text DROP TABLE #LogTemp DECLARE @clientiptext NVARCHAR(150) DECLARE @total INT DECLARE @ipstr NVARCHAR(15) DECLARE @falsecount INT DELETE FROM ManagerIP WHERE FalseCount < @MaxFalse AND LockState = 1 WHILE EXISTS ( SELECT ClientIP FROM #ErrorLog WHERE TotalFalse > @MaxFalse) BEGIN SELECT TOP 1 @clientiptext = logs.ClientIP, @total = logs.TotalFalse FROM #ErrorLog AS logs WHERE logs.TotalFalse > @MaxFalse; DELETE #ErrorLog WHERE ClientIP = @clientiptext; SET @ipstr = SUBSTRING(@clientiptext,CHARINDEX("客戶端",@clientiptext) + 5,LEN(@clientiptext) - CHARINDEX("客戶端",@clientiptext) - 5); SET @falsecount = (SELECT TOP 1 FalseCount FROM dbo.ManagerIP); IF NOT EXISTS ( SELECT * FROM dbo.ManagerIP WHERE IP = @ipstr ) BEGIN INSERT INTO dbo.ManagerIP ( IP , LockState , FalseCount , UpdateTime , TotalTimes ) VALUES ( @ipstr , -- IP - nvarchar(15) 1 , -- LockState - bit @total , -- FalseCount - int GETDATE() , -- UpdateTime - datetime 0 -- TotalTimes - int ) END ELSE IF @total < @falsecount BEGIN UPDATE dbo.ManagerIP SET FalseCount = @falsecount + @total WHERE IP = @ipstr END ELSE BEGIN UPDATE dbo.ManagerIP SET FalseCount = @total WHERE IP = @ipstr END END DROP TABLE #ErrorLog; EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35) @configvalue = 1; -- int GO RECONFIGURE; GO EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35) @configvalue = 1; -- int GO RECONFIGURE; GO DECLARE @blockips01 varchar(8000) = ""; DECLARE @blockips02 varchar(8000) = ""; DECLARE @tempip nvarchar(15) = ""; --DECLARE @addrule NVARCHAR(1000); IF OBJECT_ID(N"tempdb..#ForFirewall") IS NOT NULL BEGIN DROP TABLE #ForFirewall END CREATE TABLE #ForFirewall( BlockIP NVARCHAR(15) ); INSERT INTO #ForFirewall SELECT IP FROM dbo.ManagerIP WHERE LockState = 1 WHILE EXISTS (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP) BEGIN SET @tempip = (SELECT TOP 1 BlockIP FROM #ForFirewall ORDER BY BlockIP); IF LEN(@blockips01) > 3500 BEGIN SET @blockips02 = @blockips02 + @tempip + ","; END ELSE BEGIN SET @blockips01 = @blockips01 + @tempip + ","; END DELETE FROM #ForFirewall WHERE BlockIP = @tempip; END IF @blockips01 != "" BEGIN 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); EXEC master..xp_cmdshell @blockips01; END IF @blockips02 != "" BEGIN 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); EXEC master..xp_cmdshell @blockips02; END SELECT @blockips01 SELECT @blockips02 GO EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35) @configvalue = 0; -- int GO RECONFIGURE; GO EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35) @configvalue = 0; -- int GO RECONFIGURE; GO
執行結果如下:
此時再查看防火墻入站規則中的作用域就會發現里面多了很多的遠程IP地址。
接下來要做的就簡單多了,創建代理作業,將上面的代碼拷貝粘貼進代理作業要執行的SQL區,讓作業循環進行就可以了。這樣當惡意訪問次數操作指定次數(代碼里可以修改MaxFalse)就會被放到數據庫黑名單,同時加入防火墻阻止名單。
相關資料:
點擊查看 “xp_cmdshell”
點擊查看 “Ole Automation Procedures”
最終版本如下:
USE master; GO -- 創建IP管理表 IF OBJECT_ID("ManagerIP") IS NULL BEGIN CREATE TABLE [dbo].[ManagerIP] ( [IP] [NVARCHAR](15) NOT NULL, [LockState] [BIT] NOT NULL, [FalseCount] [INT] NOT NULL, [UpdateTime] [DATETIME] NULL, [TotalTimes] [INT] NOT NULL, CONSTRAINT [PK_ManagerIP] PRIMARY KEY CLUSTERED ([IP] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY]; END; GO IF NOT EXISTS (SELECT IP FROM dbo.ManagerIP WHERE IP = "localhost") BEGIN INSERT INTO dbo.ManagerIP ( IP, LockState, FalseCount, UpdateTime, TotalTimes ) VALUES ( N"localhost", -- IP - nvarchar(15) 0, -- LockState - bit 0, -- FalseCount - int GETDATE(), -- UpdateTime - datetime 0 -- TotalTimes - int ); END; GO --刪除日志臨時表 IF OBJECT_ID(N"TempLog") IS NOT NULL BEGIN DROP TABLE dbo.TempLog; END; --創建日志臨時表 CREATE TABLE dbo.TempLog ( [LogDate] [DATETIME] NOT NULL, [ProcessInfo] [NVARCHAR](200) NULL, [Text] [NVARCHAR](1000) NULL ); --刪除錯誤日志臨時表 IF OBJECT_ID(N"ErrorLog") IS NOT NULL BEGIN DROP TABLE dbo.ErrorLog; END; --創建錯誤日志臨時表 CREATE TABLE dbo.ErrorLog ( [ClientIP] [NVARCHAR](150) NOT NULL, [TotalFalse] [INT] NOT NULL ); --從日志臨時表篩選出登陸錯誤的日志記錄 INSERT INTO dbo.TempLog ( LogDate, ProcessInfo, Text ) EXEC sp_readerrorlog 0, 1, N"匹配", N"客戶端"; --對錯誤日志進行統計 INSERT INTO dbo.ErrorLog ( ClientIP, TotalFalse ) SELECT Text ClientIP, COUNT(*) TotalFalse FROM dbo.TempLog GROUP BY Text; GO -- 整理非法訪問的IP DECLARE @clientIP NVARCHAR(MAX); DECLARE @totalFalse INT; DECLARE @ipStr NVARCHAR(20); DECLARE @falseCount INT; DECLARE @MaxFalse INT; -- 設置允許錯誤密碼的最大次數 SET @MaxFalse = 66; DELETE FROM dbo.ManagerIP WHERE FalseCount < @MaxFalse AND LockState = 1; DECLARE LogCursor CURSOR FORWARD_ONLY READ_ONLY LOCAL FOR SELECT ClientIP, TotalFalse FROM dbo.ErrorLog WHERE TotalFalse > @MaxFalse; OPEN LogCursor; FETCH NEXT FROM LogCursor INTO @clientIP, @totalFalse; WHILE @@FETCH_STATUS = 0 BEGIN DELETE FROM dbo.ErrorLog WHERE ClientIP = @clientIP; SET @ipStr = SUBSTRING(@clientIP, CHARINDEX("客戶端", @clientIP) + 5, LEN(@clientIP) - CHARINDEX("客戶端", @clientIP) - 5); SET @falseCount = ( SELECT TOP (1) FalseCount FROM dbo.ManagerIP ORDER BY FalseCount ); IF NOT EXISTS (SELECT IP FROM dbo.ManagerIP WHERE IP = @ipStr) BEGIN INSERT INTO dbo.ManagerIP ( IP, LockState, FalseCount, UpdateTime, TotalTimes ) VALUES ( @ipStr, -- IP - nvarchar(15) 1, -- LockState - bit @totalFalse, -- FalseCount - int GETDATE(), -- UpdateTime - datetime 0 -- TotalTimes - int ); END; ELSE IF @totalFalse < @falseCount BEGIN UPDATE dbo.ManagerIP SET FalseCount = @falseCount + @totalFalse WHERE IP = @ipStr; END; ELSE BEGIN UPDATE dbo.ManagerIP SET FalseCount = @totalFalse WHERE IP = @ipStr; END; FETCH NEXT FROM LogCursor INTO @clientIP, @totalFalse; END; CLOSE LogCursor; DEALLOCATE LogCursor; -- 操作防火墻 EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35) @configvalue = 1; -- int GO RECONFIGURE; GO EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35) @configvalue = 1; -- int GO RECONFIGURE; GO DECLARE @blockips01 VARCHAR(8000) = ""; DECLARE @blockips02 VARCHAR(8000) = ""; DECLARE @tempip NVARCHAR(15) = ""; --DECLARE @addrule NVARCHAR(1000); IF OBJECT_ID(N"ForFirewall") IS NOT NULL BEGIN DROP TABLE dbo.ForFirewall; END; CREATE TABLE dbo.ForFirewall ( BlockIP NVARCHAR(15) NOT NULL ); INSERT INTO dbo.ForFirewall ( BlockIP ) SELECT IP FROM dbo.ManagerIP WHERE LockState = 1; WHILE EXISTS (SELECT TOP (1) BlockIP FROM dbo.ForFirewall ORDER BY BlockIP) BEGIN SET @tempip = ( SELECT TOP (1) BlockIP FROM dbo.ForFirewall ORDER BY BlockIP ); IF LEN(@blockips01) > 3500 BEGIN SET @blockips02 = @blockips02 + @tempip + ","; END; ELSE BEGIN SET @blockips01 = @blockips01 + @tempip + ","; END; DELETE FROM dbo.ForFirewall WHERE BlockIP = @tempip; END; IF @blockips01 <> "" BEGIN 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)); EXEC master..xp_cmdshell @blockips01; END; IF @blockips02 <> "" BEGIN 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)); EXEC master..xp_cmdshell @blockips02; END; SELECT @blockips01 Firewalls_CMD_STR_01; SELECT @blockips02 Firewalls_CMD_STR_02; GO EXEC sys.sp_configure @configname = "xp_cmdshell", -- varchar(35) @configvalue = 0; -- int GO RECONFIGURE; GO EXEC sys.sp_configure @configname = "show advanced options", -- varchar(35) @configvalue = 0; -- int GO RECONFIGURE; GO IF OBJECT_ID(N"TempLog") IS NOT NULL BEGIN DROP TABLE dbo.TempLog; END; IF OBJECT_ID(N"ErrorLog") IS NOT NULL BEGIN DROP TABLE dbo.ErrorLog; END; IF OBJECT_ID(N"ForFirewall") IS NOT NULL BEGIN DROP TABLE dbo.ForFirewall; END; GO問題匯總
小問題
在沒有將本機添加到表中的情況下創建了登陸觸發器,會讓本機也無法連接數據庫,如下面所述。
在調試SQL之前,我并沒有向表中添加數據,結果可想而知,重連數據庫就會跳出這么個東西來。
圖中分別用了“Windows 身份驗證”和“SQL Server 身份驗證”,都無法連接,頓時感覺自己真逗,把自己鎖外面了,還沒帶鑰匙。不過我相信SQL Server會兼容我這種智商的存在,網上查了下,果真可以。具體做法:
打開命令行,Ctrl + R,cmd回車;
通過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
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/17570.html
摘要:服務器垂直擴展和水平擴容資金允許的情況下,這是最簡單的一種方法,本質上講,這個方法并不是針對攻擊的,而是提升服務本身處理并發的能力,但確實提升了對攻擊的承載能力。 今天先是看到一篇討論CC攻擊的文章:Nginx防CC攻擊,緊接著就有同學在群里問我關于防CC攻擊的問題,巧嗎?好巧! 什么是CC攻擊? CC攻擊是DDoS攻擊的一種類型,使用代理服務器向受害服務器發送大量貌似合法的請求(通常...
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...
摘要:處在局域網之內的,由于有局域網出入口的網絡設備的基本保護,相對于暴露在廣域網中要安全不少,主要威脅對象基本控制在了可以接入局域網的內部潛在威脅者,和極少數能夠突破最外圍防線局域網出入口的安全設備的入侵者。 前言 對于任何一個企業來說,其數據庫系統中所保存數據的安全性無疑是非常重要的,尤其是公司的有些商業數據,可能數據就是公司的根本。 失去了數據,可能就失去了一切 本章將針對mysql...
閱讀 617·2023-04-25 18:37
閱讀 2780·2021-10-12 10:12
閱讀 8315·2021-09-22 15:07
閱讀 564·2019-08-30 15:55
閱讀 3174·2019-08-30 15:44
閱讀 2194·2019-08-30 15:44
閱讀 1625·2019-08-30 13:03
閱讀 1560·2019-08-30 12:55