[SQL]到底是誰一直在連我的資料庫呢 ?

讓 SQL Server  在網路上裸奔是很危險的事情

這一陣子遇到一些朋友將資料庫放在雲端,因為貪圖方便其他工程師 WFH 的時候可以連線,或者是因為一些業務的關係,需要讓相關的店家能連到該資料庫,因此就會把資料庫開放讓所有人可以連線,想說帳號密碼設定複雜一點就可以了,反正要猜出來應該不是那麼容易吧 ?

但是很不幸的,雖然一些亂猜帳號的不見得可以猜出密碼,但因為一堆連線卻會造成 SQL Server 的正常連線會無法正常運作,不是無法正常連上 SQL Server ,要不就是處理效能變得很慢。當這要狀況發生的時候,很多人都誤以為是 VM 的等級不夠,因此將 VM 關閉放大等級,但可能有一陣子看起來是恢復了正常,但是過沒有多久,同樣的狀況還是持續上演。

以往在課堂當中都會跟學員說,如果遇到這種情況的時候,基本上可以透過 SQL Server 內建的管理報表,查詢登入失敗的紀錄,就可以從當中找到攻擊者的 IP,此時將那些有異常攻擊的 IP 給封鎖之後,應該就可以暫時避免這樣的情況發生。因為駭客既然知道您這一台是 SQL Server,因此可能發現他的 IP 封鎖之後,就還是會換其他電腦或跳板繼續攻擊,因此只能說或許暫時可以先避開這樣的問題了。

但剛好有朋友也遇到這樣的狀況,只是當他用登入失敗的報表查看的時候,因為被攻擊的時間太長了,導致該報表幾乎沒有辦法跑完,甚至就算要匯出檔案,也匯出超過半小時以上但沒有任何效果,因此詢問是否有其他的辦法可以來查看。

基本上那個登入失敗的查詢報表,是透過 SQL Server 本身的預計 SQL Trace 來產生資料的,因此我就建議他利用系統內建的 DMV 來做處理,基本上可以使用類似以下的語法

-- 取得 SQL Trace 檔案放在哪裡
DECLARE @curr_tracefilename nvarchar(256)
select @curr_tracefilename = path FROM sys.traces where is_default = 1 ; 


-- 取得 Trace 的內容
select Error
	,StartTime
	,HostName
	,ApplicationName
	,LoginName
	,SPID
	,TextData
	,SUBSTRING(TextData, CHARINDEX('[CLIENT:', TextData ) , 64 ) IP
from ::fn_trace_gettable( @curr_tracefilename, 0 ) 
where EventClass = 20
order by StartTime
 desc

這樣就可以很快地取得相關攻擊的帳號和位址了。下圖是某一瞬間被塞瞭一堆 try 帳號的攻擊,好在透過抓到相關攻擊者的 IP 並且將那些加入黑名單,當把這些給關閉之後,系統就比較正常一點了。


基本上前面這個語法只是個範例,您還可以從這裡往下做很多的變化,像是改成類似以下的語法

DECLARE @curr_tracefilename nvarchar(256)
select @curr_tracefilename = path FROM sys.traces where is_default = 1 ; 
;
WITH List AS
(
select Error
,StartTime
,HostName
,ApplicationName
,LoginName
,SPID
,ServerName
,TextData
,SUBSTRING(TextData, CHARINDEX('[CLIENT:', TextData ) , 64 ) IP
from ::fn_trace_gettable( @curr_tracefilename, 0 ) 
where EventClass = 20 
)
SELECT LoginName,[IP],COUNT(*) AttachCount 
FROM List 
WHERE StartTime >= DATEADD( N , -30 , GETDATE() )
GROUP BY LoginName,[IP]
HAVING COUNT(*) > 1
ORDER BY AttachCount DESC

這樣每 30 分鐘抓最近有異常的狀況 , 然後可以透過 SQL Agent 和 PowerShell ,定時將有問題的位址抓出來,然後自動加入到防火牆內,這樣在管理上也就輕鬆的多了。


以上只是用圍堵的方式來進行,但如果真的要避免這樣的狀況,像是利用白名單設定可連線的電腦,然後其他都拒絕;調整 SQL Server 預設連線 1433 的 Port;避免使用部分常被攻擊的帳號,像是 sa , admin , root , administrator , test 這類常被拿來攻擊的帳號;利用 Azure 的虛擬網路,避免讓 SQL Server 暴露在 Internet 上面。這些都會是比較好的方式,降低被攻擊的機會。