IRONSOFTWAREHOME

什麼是SQL注入攻擊以及我如何在C#中防止它?

什麼是SQL注入以及如何在C#中防範它?

Tim Corey

34m 33s

SQL注入是一種程式碼注入技術,允許攻擊者通過使用者輸入將惡意的SQL程式碼發送到您的資料庫伺服器。 在他的视频"什麼是SQL注入以及如何在C#中防範它?"中,Tim Corey演示了SQL注入漏洞如何出現在真實程式碼中,展示了幾個成功的SQL注入攻擊範例(包括基於union的和破壞性的攻擊),並逐步解釋了您可以在C#中應用的實用SQL注入防範技術。 本文跟隨Tim的步驟說明,讓您能看到他顯示的具體問題和修復。

示範應用程式及其重要性

Tim從一個小型WPF示範應用程式開始,其連接到本地InjectableDB(人員和機密表)。 該應用程式的網頁形式搜尋框接受使用者輸入(姓氏),並構建SQL查詢以返回ID、名字和姓氏。 它"運作正常"——輸入Corey並獲得Tim Corey——但Tim強調核心要點:"僅僅因為應用程式正常運行並不意味著其安全。" 一個正常運行的網頁應用程式仍可能在使用者提供的輸入直接插入SQL語句時存在SQL注入漏洞。

不安全程式碼——字串連接和動態SQL

Tim展示了許多開發人員使用的確切不安全模式:

var sql = $"SELECT * FROM People WHERE LastName = '{searchText}'";
var results = connection.Query<Person>(sql);

此原始查詢使用字串連接來建立SQL語句。 Tim警告:如果您看到程式碼將使用者輸入直接插入SQL查詢,請停止——這是SQL注入漏洞。 攻擊者可以製造惡意輸入來更改您的SQL命令結構,甚至運行附加的惡意SQL語句。

攻擊者如何利用——UNION和DROP

為了展示SQL注入攻擊如何工作,Tim在SQL Server中複製查詢,然後使用UNION ALL和SQL註釋(--)來隱藏尾隨字元製造注入。 Tim展示的範例惡意有效載荷:

  • 基於UNION的SQL注入以讀取其他表:

    UNION ALL SELECT ID, Username AS FirstName, Password AS LastName FROM Secrets;
    Text

    這將Secrets中的結果混合到原始SELECT結果集中,暴露使用者名和密碼等敏感資料。

  • 破壞性注入以刪除表:

    DROP TABLE DemoTable;
    Text

    這通過用分號終止第一個語句並新增破壞性命令來運行第二條SQL語句(DROP TABLE)。 Tim顯示表消失了——資料庫已被惡意SQL修改。

Tim的觀點:攻擊者不需要提前知道表或列名——他們可以從資料庫伺服器枚舉表或列名,或者僅僅嘗試盲目或基於時間的技術來發現行為。

修復1——參數化查詢

Tim的第一個且主要防禦是停止以使用者資料構建SQL字串。 用參數化查詢替換動態SQL:

string sql = "SELECT * FROM People WHERE LastName = @LastName";
var results = connection.Query<Person>(sql, new { LastName = searchText });

Tim解釋說,參數化(事先準備好的語句樣式使用)表示資料庫將使用者提供的輸入嚴格視為資料——惡意SQL僅成為字串值,不能改變SQL結構。 這防止了許多常見的SQL注入攻擊,包括基於union的有效載荷和追加的; DROP TABLE命令。

他還建議將參數化與最小輸入驗證配對:消毒或封鎖不太可能出現在姓氏中的字元(例如,分號或--註釋標記),同時允許合法字元如撇號(O'Reilly)。 參數化查詢 + 輸入清理提供了實質上的SQL注入攻擊保護。

修復2——儲存過程

Tim接著展示了兩個儲存過程:一個不安全的儲存過程,其內部連接SQL後再執行,和一個安全的儲存過程,直接使用參數。

  • 不安全的儲存過程從參數構建一個@sql字串並執行它——仍然易受注入攻擊。

  • 安全儲存過程執行SELECT ... WHERE LastName = @LastName 並使用參數執行——安全。

Tim澄清說:如果您仍在其中構建動態SQL,儲存過程並不是自動的解決方案。 但當正確使用時(無動態SQL),儲存過程有助於集中化SQL語句,使查詢更易於參數化和審核。 儲存過程還能有助於簡化應用程式中的SQL注入防範。

不要信任任何資料——即使是資料庫資料

Tim提出的重要但往往被忽視的觀點:您不能盲目信任從您自己的SQL資料庫檢索到的資料。 攻擊者有時會在列中植入惡意有效載荷("滴答定時炸彈"),這些載荷稍後會被另一個過程串接到動態SQL中。 Tim堅持說:始終使用參數並在每一步驟消毒資料——無論它來自網頁表單、文件上傳或您自己的資料庫——以便惡意輸入後不能成為注入的途徑。

額外提示——最低權限和限制資料庫權限

除了程式碼修復外,Tim建議防禦性配置:限制您的應用程式帳戶的資料庫權限。 在他的演示中,連接使用通過整合安全性的管理員帳戶——這很危險。 相反,使用最低權限原則:

  • 為應用程式建立一個僅具有所需權限的資料庫帳戶。

  • 如果您使用儲存程式,則僅給該帳戶授予特定儲存程式的EXECUTE權限,其他的不授予。

  • 不要給應用程式帳戶廣泛的管理員權限,允許DROP TABLE、列出所有表或讀取其他資料庫。

這減少了成功SQL注入攻擊的影響——即使有可能進行注入,攻擊者也無法超出該帳戶的允許範圍。

Tim還指出Entity Framework使這變得複雜:EF通常需要提升的權限(遷移、架構更改)。 如果您在生產中使用EF,需仔細計劃其權限和部署。

回顧——停止,參數化,消毒,限制

Tim在他的影片中總結了一個明確清單,以防止C#應用程式中的SQL注入:

  1. 停止使用包含使用者輸入的字串連接或動態SQL構建SQL語句。

  2. 使用參數化查詢/預備語句模式,以便使用者資料始終被當作資料處理。

  3. 在適當位置消毒輸入(阻止分號、SQL註釋、非預期字元)。

  4. 偏好安全的儲存程式(其內部無動態SQL)以集中查詢邏輯。

  5. 將最低權限應用于資料庫帳戶——限制應用程式資料庫使用者的權限。

  6. 審查程式碼(尤其是那些動態構建SQL的地方)並測試SQL注入漏洞。

Tim的最後警告:不當處理使用者輸入、動態SQL和過多的資料庫特權可導致嚴重的洩漏——敏感資料洩露,表被破壞或持續未檢測的資料外流。 將SQL注入防範視為核心安全要求,而非選擇性美化。

Earn More by Sharing What You Love

Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Let's Stay in Touch!

Join our newsletter, you’ll get exclusive access on article updates. We value your privacy

Key in blue circle

立即免費取得 30 天試用金鑰

Your trial license will be sent to your email address

無任何限制。100% 解鎖。無需信用卡。

bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
獲取您的無義務諮詢
填寫以下表格或發送電子郵件至sales@ironsoftware.com
您的詳細資訊將始終保密。
被全球數百萬工程師信任
Iron Software的客戶標誌
立即獲取您的30天試用金鑰
無需信用卡或帳戶建立