201612071551[MSSQL] 刪除資料庫被插入的惡意內容 - SQL 字串函數處理

 當發生資料庫 SQL Injection 時,其欄位資料就很有可能被插入程式碼(通常該欄位是網頁、HTML的儲存欄位),其目的是要正常的使用者瀏覽該網頁時,就自動的執行連線到惡意程式碼所指定的地方,以現在綁架軟體或殭屍病毒這麼盛行,大家要注意自己的網頁避免被插入惡意的 Javascript 或 HTML。

這篇的討論是當被插入惡意程式碼後的處理方式,

難處:被插入惡意程式碼的欄位
> 原始資料長度不一
> 惡意碼長度不一
> 插入點的位置
> 有無特徵可以判斷
> 筆數太大量,無法單純用人工刪除
> 不是每筆都有被插入惡意碼

--------------------------------------------------------------------------
這次被攻擊的插入惡意碼,類似
<div style="display:none"> arcoxia 90 cena, Can i take antabuse and nal......< a href="http://xxx.xxx/xxx"> link </a> arcoxia 120 mg </div>
但長度、筆數不一,沒辦法單純的用 cut 方式來處理
--------------------------------------------------------------------------

底下將介紹 SQL 字串的處理方式

 字串函數 (Transact-SQL)  https://msdn.microsoft.com/zh-tw/library/ms181984(v=sql.120).aspx 

ASCII 傳回字元 ASCII 值。如果有多個字元會回傳最左邊的字元ASCII 碼
SELECT ASCII('A')
回傳> 65

CHAR 將 int ASCII 碼轉換成字元。
SELECT CHAR(65)
回傳> A

CHARINDEX 搜尋指定內容是否有關鍵字,若無傳回0,有則傳回位元的所在位置。若內容中有多比符合關鍵字,則只會傳回第一個位置,要多次搜尋可搭配第3個起始位置的參數。 CHARINDEX ( 關鍵字 , 被搜尋之內容 [ , 起始位置(可省略) ] )
Declare @xstr varchar(100);
Set @xstr = 'Life is the art of drawing sufficient conclusions form insufficient premises.';
SELECT CHARINDEX('sufficient', @xstr);
SELECT CHARINDEX('sufficient', @xstr, CHARINDEX('sufficient', @xstr)+1);
回傳> 28
回傳> 58

CONCAT 字串串接  CONCAT ( 字串1, 字串2 [, 字串N ] )
在 SQL 2008 R2 沒有該函數,可以簡單使用 + 加號就可以串接字串。

DIFFERENCE 傳回一個整數值 介於0~4,0:不相似,4:相似。比較的基準是以 SOUNDEX 值之間的差異。
SELECT DIFFERENCE('Green','Greenth');
SELECT DIFFERENCE('Green','Yellow');
回傳>3
回傳>0

FORMAT 傳回以 SQL Server 2014 中指定的格式與選用文化特性格式化的值。 將 FORMAT 函數用於將日期/時間與數值視為字串的地區設定感知格式化作業。 針對一般資料類型轉換,請使用 CAST 或 CONVERT。
SQL 2008 不支援
SELECT '$ ' + format(123456789, '###,###,###');
回傳> $ 123,456,789
SELECT format(getdate(), 'yyyy/MM/dd');
回傳> 2016/12/07
SELECT format(getdate(), 'D', 'en-US');
回傳> Wednesday, December 7,2016

LEFT 取得指定內容「左邊」固定字元數的字元。
RIGHT  得指定內容「右邊」固定字元數的字元
Declare @xstr varchar(100);
Set @xstr = 'Life is the art of drawing sufficient conclusions form insufficient premises.';
SELECT LEFT(@xstr, 10);
SELECT RIGHT(@xstr,6);
回傳> Life is th
回傳> mises.

LEN 取得字串長度。
LOWER  將大寫字元轉換成小寫。
UPPER   將小寫字元轉換成大寫
select UPPER('Superman'), LOWER('Superman');
回傳> SUPERMAN
回傳> superman

LTRIM 傳回移除左邊空白的字元。
RTRIM  傳回移除右邊空白的字元。
declare @xx char(20) = 'hello';
select @xx;
select RTRIM(@xx);
回傳> hello               <- 因為為 char 欄位,所以又會被填上空格
回傳> hello<- 可用 rtrim 來去除多餘空白

PATINDEX  搜尋指定內容是否有關鍵字,若無傳回0,有則傳回位元的所在位置PATINDEX ( '%關鍵字%' , 要被搜尋的內容 )  ,關鍵字前後都要加 % ,若沒加 % 必須完全 match (關鍵字=被搜尋的內容)多個空白都不行。
Declare @xstr varchar(100) = 'Life is the art of drawing sufficient conclusions form insufficient premises.';
SELECT patindex('%sufficient%', @xstr);
回傳>28

REPLACE 將字串取代成另一個字串  REPLACE ( 處理的內容 , 欲變更的字串 , 變更後的字串 )
Declare @xstr varchar(100) = 'Life is the art of drawing sufficient conclusions form insufficient premises.';
SELECT REPLACE(@xstr,'sufficient','^_^!');
回傳>Life is the art of drawing ^_^! conclusions form in^_^! premises.

REPLICATE 將字串值重複指定的次數。可填補到指定的長度 REPLICATE ( 欲複製的字元 ,複製次數) 
select 'Hello' + REPLICATE(' ',8)+ 'Superman!'
回傳>Hello        Superman!
declare @n1 varchar(5) = 123;
declare @n2 varchar(5) = 4;
declare @n3 varchar(5) = 7890;
select REPLICATE('0',4-len(@n1))+@n1 , REPLICATE('0',4-len(@n2))+@n2 , REPLICATE('0',4-len(@n3))+@n3
回傳> 0123
回傳> 0004
回傳> 7890
註:REPLICATE('0',4-len(@n3))+@n3   若 4 < len(@n3) ,則串接起來的結果會變成 NULL ,所以需注意填上的補0數量

SPACE  填入空格字串,但如果欄位是 unicode 請改用 replicate。
select 'Hello' + space(2)+ 'Superman!'
回傳> Hello  Superman!

REVERSE  傳回字串值的反轉順序。整個字串內容反轉
Declare @xstr varchar(100) = 'Life is the art of drawing sufficient conclusions form insufficient premises.';
select REVERSE(@xstr);
回傳> .sesimerp tneiciffusni mrof snoisulcnoc tneiciffus gniward fo tra eht si efiL

STR  數值格式化轉換成字元。
declare @xfloat float = 567.2;
select @xfloat, STR(@xfloat,8,3);
回傳> 567.2
回傳> 567.200

STUFF  指定位置、長度替換成指定的字串內容  STUFF ( 欲變動的內容 , 開始位置 , 長度 , 變更的字串 )
declare @xnum varchar(20) = '1234567890';
select STUFF(@xnum, 3, 2 ,'_abcdefgh_');
回傳> 12_abcdefgh_567890
註:如果長度指定為0,這 stuff 指令可當作「插入 insert」來使用
declare @xnum varchar(20) = '1234567890';
select STUFF(@xnum, 3, 0 ,'_abcdefgh_');
回傳>12_abcdefgh_34567890

SUBSTRING  截取部分字串,可用在 character、binary、text、ntext 或 image。SUBSTRING ( 內容 ,起始位置 , 長度 )
declare @xnum varchar(20) = '1234567890';
select SUBSTRING(@xnum,3,5);
回傳>34567

UNICODE  轉換文字為 unicode 編碼值(若內容有多個文字,則只會轉換第一個字),可利用 NCHAR 再轉回來
select UNICODE('我'), NCHAR(25105);
回傳>25105
回傳> 



----------------------------------------------------------------------------------------------------------------------------

經過上面介紹 MSSQL 的字串相關的處理指令介紹,可以得知要
標示出關鍵字位置的指令有 CHARINDEX PATINDEX 
字串取代的指令有、REPLACE SUBSTRING 
搭配的處理指令有  LEN

惡意程式碼各種不同的狀態

 

針對狀況1與狀況2
被插入的惡意程式碼都帶有特定的關鍵字,而且都被加在原本內容的最後面,這也是最多 SQL Injection 被插入的狀況,所以要找出受影響的內容

以我自己的例子來說,關鍵字是「<div style="display:none">」,因為攻擊者希望不要影響原本瀏覽網頁的效果,又要可以自動連線到指定的網址,所以會用 display:none 來藏起來

Declare @xstr vatchar(100) = '<div style="display:none">';
SELECT  REPLACE(content, SUBSTRING(content, CHARINDEX(@xstr,[content]), LEN([content])), ' ') as replaced
FROM hacked_table
WHERE keyword='%<div style="display:none">%'

這樣就能找出 contnet 欄位 被插入具有關鍵字的內容,然後以 replace 函式將他去除掉,當然上面只是 select 出來,要真正去除惡意程式碼還是得用 update 的SQL指令來執行

建議大家還是先備份,再繼續後續的 update 更新吧!最好當然是在 duplicate 一份資料表,測試OK後再到正式的資料表去執行
select *  into new_dup_table from org_table

declare @xstr varchar(100) = 'keyword';
update dbname.dbo.your_table
set content = REPLACE(content, SUBSTRING(content, CHARINDEX(@xstr,[content]), LEN([content])), ' ') 
where content like '%keyword%'

 

狀況3 是沒受害的欄位內容,但必須避免被無端的更新,需小心以 update 的 where 去排除

狀況4 這是最麻煩的情況,關鍵字被穿插在正常的文章中,這就必須找到插入的惡意程式碼結尾,有無另一個特徵值供抓取定位,有辦法區分出來才能以 REPLACE 去取代、刪除。

~End

回應
Google Search
Google
平均分數:0 顆星
投票人數:0
我要評分:
Google