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 字串的處理方式
SELECT ASCII('A')
回傳> 65
SELECT CHAR(65)
回傳> A
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
在 SQL 2008 R2 沒有該函數,可以簡單使用 + 加號就可以串接字串。
SELECT DIFFERENCE('Green','Greenth');
SELECT DIFFERENCE('Green','Yellow');
回傳>3
回傳>0
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
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.
select UPPER('Superman'), LOWER('Superman');
回傳> SUPERMAN
回傳> superman
declare @xx char(20) = 'hello';
select @xx;
select RTRIM(@xx);
回傳> hello <- 因為為 char 欄位,所以又會被填上空格
回傳> hello<- 可用 rtrim 來去除多餘空白
Declare @xstr varchar(100) = 'Life is the art of drawing sufficient conclusions form insufficient premises.';
SELECT patindex('%sufficient%', @xstr);
回傳>28
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.
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數量
select 'Hello' + space(2)+ 'Superman!'
回傳> Hello Superman!
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
declare @xfloat float = 567.2;
select @xfloat, STR(@xfloat,8,3);
回傳> 567.2
回傳> 567.200
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
declare @xnum varchar(20) = '1234567890';
select SUBSTRING(@xnum,3,5);
回傳>34567
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