日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
SQL注入

SQL 注入是一種攻擊方式,在這種攻擊方式中,惡意代碼被插入到字符串中,然后將該字符串傳遞到 SQL Server 的實例以進行分析和執(zhí)行。任何構成 SQL 語句的過程都應進行注入漏洞檢查,因為 SQL Server 將執(zhí)行其接收到的所有語法有效的查詢。一個有經(jīng)驗的、堅定的攻擊者甚至可以操作參數(shù)化數(shù)據(jù)。

創(chuàng)新互聯(lián)公司:從2013年創(chuàng)立為各行業(yè)開拓出企業(yè)自己的“網(wǎng)站建設”服務,為上1000家公司企業(yè)提供了專業(yè)的網(wǎng)站建設、網(wǎng)站制作、網(wǎng)頁設計和網(wǎng)站推廣服務, 按需搭建網(wǎng)站由設計師親自精心設計,設計的效果完全按照客戶的要求,并適當?shù)奶岢龊侠淼慕ㄗh,擁有的視覺效果,策劃師分析客戶的同行競爭對手,根據(jù)客戶的實際情況給出合理的網(wǎng)站構架,制作客戶同行業(yè)具有領先地位的。

SQL 注入的主要形式包括直接將代碼插入到與 SQL 命令串聯(lián)在一起并使其得以執(zhí)行的用戶輸入變量。一種間接的攻擊會將惡意代碼注入要在表中存儲或作為元數(shù)據(jù)存儲的字符串。在存儲的字符串隨后串連到一個動態(tài) SQL 命令中時,將執(zhí)行該惡意代碼。

注入過程的工作方式是提前終止文本字符串,然后追加一個新的命令。由于插入的命令可能在執(zhí)行前追加其他字符串,因此攻擊者將用注釋標記“--”來終止注入的字符串。執(zhí)行時,此后的文本將被忽略。

以下腳本顯示了一個簡單的 SQL 注入。此腳本通過串聯(lián)硬編碼字符串和用戶輸入的字符串而生成一個 SQL 查詢:

 
 
 
  1. var Shipcity;
  2. ShipCity = Request.form ("ShipCity");
  3. var sql = "select * from OrdersTable where ShipCity = '" + ShipCity + "'";

用戶將被提示輸入一個市縣名稱。如果用戶輸入 Redmond,則查詢將由與下面內(nèi)容相似的腳本組成:

 
 
 
  1. SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond'

但是,假定用戶輸入以下內(nèi)容:

Redmond'; drop table OrdersTable--

此時,腳本將組成以下查詢:

 
 
 
  1. SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond';drop table OrdersTable--'

分號 (;) 表示一個查詢的結束和另一個查詢的開始。雙連字符 (--) 指示當前行余下的部分是一個注釋,應該忽略。如果修改后的代碼語法正確,則服務器將執(zhí)行該代碼。SQL Server 處理該語句時,SQL Server 將首先選擇 OrdersTable 中的所有記錄(其中 ShipCity 為 Redmond)。然后,SQL Server 將刪除 OrdersTable。

只要注入的 SQL 代碼語法正確,便無法采用編程方式來檢測篡改。因此,必須驗證所有用戶輸入,并仔細檢查在您所用的服務器中執(zhí)行構造 SQL 命令的代碼。本主題中的以下各部分說明了編寫代碼的最佳做法。

驗證所有輸入

始終通過測試類型、長度、格式和范圍來驗證用戶輸入。實現(xiàn)對惡意輸入的預防時,請注意應用程序的體系結構和部署方案。請注意,設計為在安全環(huán)境中運行的程序可能會被復制到不安全的環(huán)境中。以下建議應被視為最佳做法:

對應用程序接收的數(shù)據(jù)不做任何有關大小、類型或內(nèi)容的假設。例如,您應該進行以下評估:

如果一個用戶在需要郵政編碼的位置無意中或惡意地輸入了一個 10 MB 的 MPEG 文件,應用程序會做出什么反應?

如果在文本字段中嵌入了一個 DROP TABLE 語句,應用程序會做出什么反應?

測試輸入的大小和數(shù)據(jù)類型,強制執(zhí)行適當?shù)南拗?。這有助于防止有意造成的緩沖區(qū)溢出。

測試字符串變量的內(nèi)容,只接受所需的值。拒絕包含二進制數(shù)據(jù)、轉(zhuǎn)義序列和注釋字符的輸入內(nèi)容。這有助于防止腳本注入,防止某些緩沖區(qū)溢出攻擊。

使用 XML 文檔時,根據(jù)數(shù)據(jù)的架構對輸入的所有數(shù)據(jù)進行驗證。

絕不直接使用用戶輸入內(nèi)容來生成 Transact-SQL 語句。

使用存儲過程來驗證用戶輸入。

在多層環(huán)境中,所有數(shù)據(jù)都應該在驗證之后才允許進入可信區(qū)域。未通過驗證過程的數(shù)據(jù)應被拒絕,并向前一層返回一個錯誤。

實現(xiàn)多層驗證。對無目的的惡意用戶采取的預防措施對堅定的攻擊者可能無效。更好的做法是在用戶界面和所有跨信任邊界的后續(xù)點上驗證輸入。

例如,在客戶端應用程序中驗證數(shù)據(jù)可以防止簡單的腳本注入。但是,如果下一層認為其輸入已通過驗證,則任何可以繞過客戶端的惡意用戶就可以不受限制地訪問系統(tǒng)。

絕不串聯(lián)未驗證的用戶輸入。字符串串聯(lián)是腳本注入的主要輸入點。

在可能據(jù)以構造文件名的字段中,不接受下列字符串:AUX、CLOCK$、COM1 到 COM8、CON、CONFIG$、LPT1 到 LPT8、NUL 以及 PRN。

如果可能,拒絕包含以下字符的輸入。

輸入字符
 在 Transact-SQL 中的含義
 
;
 查詢分隔符。
 
'
 字符數(shù)據(jù)字符串分隔符。
 
--
 注釋分隔符。
 
/* ... */
 注釋分隔符。服務器不對 /* 和 */ 之間的注釋進行處理。
 
xp_
 用于目錄擴展存儲過程的名稱的開頭,如 xp_cmdshell。

使用類型安全的 SQL 參數(shù)
SQL Server 中的 Parameters 集合提供了類型檢查和長度驗證。如果使用 Parameters 集合,則輸入將被視為文字值而不是可執(zhí)行代碼。使用 Parameters 集合的另一個好處是可以強制執(zhí)行類型和長度檢查。范圍以外的值將觸發(fā)異常。以下代碼段顯示了如何使用 Parameters 集合:

 
 
 
  1. SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn);
  2. myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
  3. SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id",
  4.      SqlDbType.VarChar, 11);
  5. parm.Value = Login.Text;

在此示例中,@au_id 參數(shù)被視為文字值而不是可執(zhí)行代碼。將對此值進行類型和長度檢查。如果 @au_id 值不符合指定的類型和長度約束,則將引發(fā)異常。

在存儲過程中使用參數(shù)化輸入
存儲過程如果使用未篩選的輸入,則可能容易受 SQL Injection 攻擊。例如,以下代碼容易受到攻擊:

 
 
 
  1. SqlDataAdapter myCommand = 
  2. new SqlDataAdapter("LoginStoredProcedure '" + 
  3.                                Login.Text + "'", conn);

如果使用存儲過程,則應使用參數(shù)作為存儲過程的輸入。

在動態(tài) SQL 中使用參數(shù)集合

如果不能使用存儲過程,您仍可使用參數(shù),如以下代碼示例所示:

 
 
 
  1. SqlDataAdapter myCommand = new SqlDataAdapter(
  2. "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", conn);
  3. SQLParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id", 
  4.                         SqlDbType.VarChar, 11);
  5. Parm.Value = Login.Text;

篩選輸入
篩選輸入可以刪除轉(zhuǎn)義符,這也可能有助于防止 SQL 注入。但由于可引起問題的字符數(shù)量很大,因此這并不是一種可靠的防護方法。以下示例可搜索字符串分隔符。

復制代碼
private string SafeSqlLiteral(string inputSQL)
{
  return inputSQL.Replace("'", "''");
}
LIKE 子句
請注意,如果要使用 LIKE 子句,還必須對通配符字符進行轉(zhuǎn)義:

復制代碼
s = s.Replace("[", "[[]");
s = s.Replace("%", "[%]");
s = s.Replace("_", "[_]");
  在代碼中檢查 SQL 注入
應檢查所有調(diào)用 EXECUTE、EXEC 或 sp_executesql 的代碼??梢允褂妙愃迫缦碌牟樵儊韼椭鷺俗R包含這些語句的過程。此查詢檢查單詞 EXECUTE 或 EXEC 后是否存在 1 個、2 個、3 個或 4 個空格。

 
 
 
  1. SELECT object_Name(id) FROM syscomments
  2. WHERE UPPER(text) LIKE '%EXECUTE (%'
  3. OR UPPER(text) LIKE '%EXECUTE  (%'
  4. OR UPPER(text) LIKE '%EXECUTE   (%'
  5. OR UPPER(text) LIKE '%EXECUTE    (%'
  6. OR UPPER(text) LIKE '%EXEC (%'
  7. OR UPPER(text) LIKE '%EXEC  (%'
  8. OR UPPER(text) LIKE '%EXEC   (%'
  9. OR UPPER(text) LIKE '%EXEC    (%'
  10. OR UPPER(text) LIKE '%SP_EXECUTESQL%'

使用 QUOTENAME() 和 REPLACE() 包裝參數(shù)

在選擇的每個存儲過程中,驗證是否對動態(tài) Transact-SQL 中使用的所有變量都進行了正確處理。來自存儲過程的輸入?yún)?shù)的數(shù)據(jù)或從表中讀取的數(shù)據(jù)應包裝在 QUOTENAME() 或 REPLACE() 中。請記住,傳遞給 QUOTENAME() 的 @variable 值的數(shù)據(jù)類型為 sysname,且最大長度為 128 個字符。

@variable
 建議的包裝
 
安全對象的名稱
 QUOTENAME(@variable)
 
字符串 ≤ 128 個字符
 QUOTENAME(@variable, '''')
 
字符串 > 128 個字符
 REPLACE(@variable,'''', '''''')

使用此方法時,可對 SET 語句進行如下修改:

--Before:

SET @temp = N'select * from authors where au_lname='''

+ @au_lname + N''''

--After:

SET @temp = N'select * from authors where au_lname='''

+ REPLACE(@au_lname,'''','''''') + N''''

由數(shù)據(jù)截斷啟用的注入
如果分配給變量的任何動態(tài) Transact-SQL 比為該變量分配的緩沖區(qū)大,那么它將被截斷。如果攻擊者能夠通過將意外長度的字符串傳遞給存儲過程來強制執(zhí)行語句截斷,則該攻擊者可以操作該結果。例如,以下腳本創(chuàng)建的存儲過程容易受到由截斷啟用的注入攻擊。

 
 
 
  1. CREATE PROCEDURE sp_MySetPassword
  2. @loginname sysname,
  3. @old sysname,
  4. @new sysname
  5. AS
  6. -- Declare variable.
  7. -- Note that the buffer here is only 200 characters long.
  8. DECLARE @command varchar(200)
  9. -- Construct the dynamic Transact-SQL.
  10. -- In the following statement, we need a total of 154 characters
  11. -- to set the password of 'sa'.
  12. -- 26 for UPDATE statement, 16 for WHERE clause, 4 for 'sa', and 2 for
  13. -- quotation marks surrounded by QUOTENAME(@loginname):
  14. -- 200 – 26 – 16 – 4 – 2 = 154.
  15. -- But because @new is declared as a sysname, this variable can only hold
  16. -- 128 characters.
  17. -- We can overcome this by passing some single quotation marks in @new.
  18. SET @command= 'update Users set password=' + QUOTENAME(@new, '''') + ' where username=' + QUOTENAME(@loginname, '''') + ' AND password = ' + QUOTENAME(@old, '''')
  19. -- Execute the command.
  20. EXEC (@command)
  21. GO

通過向 128 個字符的緩沖區(qū)傳遞 154 個字符,攻擊者便可以在不知道舊密碼的情況下為 sa 設置新密碼。

EXEC sp_MySetPassword 'sa', 'dummy', '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012'''''''''''''''''''''''''''''''''''''''''''''''''''

因此,應對命令變量使用較大的緩沖區(qū),或直接在 EXECUTE 語句內(nèi)執(zhí)行動態(tài) Transact-SQL。

使用 QUOTENAME(@variable, '''') 和 REPLACE() 時的截斷
如果 QUOTENAME() 和 REPLACE() 返回的字符串超過了分配的空間,該字符串將被自動截斷。以下示例中創(chuàng)建的存儲過程顯示了可能出現(xiàn)的情況。

 
 
 
  1. CREATE PROCEDURE sp_MySetPassword
  2. @loginname sysname,
  3. @old sysname,
  4. @new sysname
  5. AS
  6. -- Declare variables.
  7. DECLARE @login sysname
  8. DECLARE @newpassword sysname
  9. DECLARE @oldpassword sysname
  10. DECLARE @command varchar(2000)
  11. -- In the following statements, the data stored in temp variables
  12. -- will be truncated because the buffer size of @login, @oldpassword,
  13. -- and @newpassword is only 128 characters, but QUOTENAME() can return
  14. -- up to 258 characters.
  15. SET @login = QUOTENAME(@loginname, '''')
  16. SET @oldpassword = QUOTENAME(@old, '''')
  17. SET @newpassword = QUOTENAME(@new, '''')
  18. -- Construct the dynamic Transact-SQL.
  19. -- If @new contains 128 characters, then @newpassword will be '123... n
  20. -- where n is the 127th character.
  21. -- Because the string returned by QUOTENAME() will be truncated,
  22. -- it can be made to look like the following statement:
  23. -- UPDATE Users SET password ='1234. . .[127] WHERE username=' -- other stuff here
  24. SET @command = 'UPDATE Users set password = ' + @newpassword
  25. + ' where username =' + @login + ' AND password = ' + @oldpassword;
  26. -- Execute the command.
  27. EXEC (@command)
  28. GO

因此,以下語句將把所有用戶的密碼都設置為在前面的代碼中傳遞的值。

EXEC sp_MyProc '--', 'dummy', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678'

使用 REPLACE() 時,可以通過超出分配的緩沖區(qū)空間來強迫字符串截斷。以下示例中創(chuàng)建的存儲過程顯示了可能出現(xiàn)的情況。

 
 
 
  1. CREATE PROCEDURE sp_MySetPassword
  2. @loginname sysname,
  3. @old sysname,
  4. @new sysname
  5. AS
  6. -- Declare variables.
  7. DECLARE @login sysname
  8. DECLARE @newpassword sysname
  9. DECLARE @oldpassword sysname
  10. DECLARE @command varchar(2000)
  11. -- In the following statements, data will be truncated because
  12. -- the buffers allocated for @login, @oldpassword and @newpassword
  13. -- can hold only 128 characters, but QUOTENAME() can return
  14. -- up to 258 characters.
  15. SET @login = REPLACE(@loginname, '''', '''''')
  16. SET @oldpassword = REPLACE(@old, '''', '''''')
  17. SET @newpassword = REPLACE(@new, '''', '''''')
  18. -- Construct the dynamic Transact-SQL.
  19. -- If @new contains 128 characters, @newpassword will be '123...n
  20. -- where n is the 127th character.
  21. -- Because the string returned by QUOTENAME() will be truncated, it
  22. -- can be made to look like the following statement:
  23. -- UPDATE Users SET password='1234…[127] WHERE username=' -- other stuff here
  24. SET @command= 'update Users set password = ''' + @newpassword + ''' where username='''
  25. + @login + ''' AND password = ''' + @oldpassword + '''';
  26. -- Execute the command.
  27. EXEC (@command)
  28. GO

與 QUOTENAME() 一樣,可以通過聲明對所有情況都足夠大的臨時變量來避免由 REPLACE() 引起的字符串截斷。應盡可能直接在動態(tài) Transact-SQL 內(nèi)調(diào)用 QUOTENAME() 或 REPLACE()。或者,也可以按如下方式計算所需的緩沖區(qū)大小。對于 @outbuffer = QUOTENAME(@input),@outbuffer 的大小應為 2*(len(@input)+1). 。使用 REPLACE() 和雙引號時(如上一示例),大小為 2*len(@input) 的緩沖區(qū)便已足夠。

以下計算涵蓋所有情況:

While len(@find_string) > 0, required buffer size =

round(len(@input)/len(@find_string),0) * len(@new_string)

+ (len(@input) % len(@find_string))

使用 QUOTENAME(@variable, ']') 時的截斷
當 SQL Server 安全對象的名稱被傳遞給使用 QUOTENAME(@variable, ']') 形式的語句時,可能發(fā)生截斷。下面的示例顯示了這種情況。

 
 
 
  1. CREATE PROCEDURE sp_MyProc
  2. @schemaname sysname,
  3. @tablename sysname,
  4. AS
  5. -- Declare a variable as sysname. The variable will be 128 characters.
  6. -- But @objectname actually must allow for 2*258+1 characters.
  7. DECLARE @objectname sysname
  8. SET @objectname = QUOTENAME(@schemaname)+'.'+ QUOTENAME(@tablename)
  9. -- Do some operations.
  10. GO

當您串聯(lián) sysname 類型的值時,應使用足夠大的臨時變量來保存每個值的最多 128 個字符。應盡可能直接在動態(tài) Transact-SQL 內(nèi)調(diào)用 QUOTENAME()?;蛘?,也可以按上一部分所述來計算所需的緩沖區(qū)大小。

原文地址

本文來源:微軟TechNet中文站


本文標題:SQL注入
URL地址:http://www.5511xx.com/article/dpigogs.html