2014-12-02 35 views
5

我完全意識到清理SQL查詢的正確做法是對它們進行參數化。替換'轉義字符後T-SQL的安全性如何?

我在很多預先存在的代碼上工作,其中衛生措施是用動態字符串替換所有'的場合與''。我想弄清楚我應該如何擔心。

事情是這樣的:這個代碼運行在T-SQL專門(SQL服務器2008 R2及更高版本),而且據我所知,'是T-SQL的只有轉義字符。

那麼,你將如何執行注入攻擊闖過上述措施?即在T-SQL上,這種非常「幼稚」的衛生方式確實非常穩固,因爲它看起來像?

+3

可以用其十六進制表示法或其Unicode表示法替換單引號字符,或者可以通過預期該行爲並使用適當數量的單引號,這樣你的「衛生」就完全失敗了...... **認真**:不要這樣做。 ***永遠不會*** - 使用parmae​​ters - ***總是*** – 2014-12-02 09:00:59

+1

@marc_s請寫一個插入語句,插入1000行50個字段。如果你能做到這一點(提示:你不能),那麼我稱這是一個很好的評論。否則:無知。參數的數量是有限的,有時使用另一種方法是很好的情況。 – TomTom 2014-12-02 15:38:02

+2

如果你正在做的TomTom使用SQLBulkCopy - marc_s是正確的,至少有關使用參數 – Swomble 2014-12-02 15:42:00

回答

3

是的,單引號是唯一的轉義字符,所以你主要是,主要是,但並不完全正確。

使用參數,而最好的,大多隻是做了'''更換你正在做手工。但是,他們也強制執行最大字符串長度。當然,如果我們談論的是非字符串參數,他們會有強制執行數據類型的好處(例如,'不需要轉義爲數字,日期/時間等類型,因爲它無效他們開始)。

您可能仍然留下的問題是SQL注入的一個子集,稱爲SQL截斷。這個想法是強制動態sql的一部分離開字符串的末尾。我不確定這種情況在實際中會發生多少,但根據構建動態SQL的方式和位置,您需要確保持有要執行的動態SQL的變量足夠大以將靜態塊保存在你的代碼加上所有的變量,假設它們以最大長度提交。

這是來自MSDN Magazine,New SQL Truncation Attacks And How To Avoid Them的文章,它顯示了常規SQL注入以及SQL截斷。您將在文章中看到,爲避免SQL注入,他們大多隻是執行REPLACE(@variable, '''', '''''')方法,但在某些情況下也會顯示使用QUOTENAME(@variable, '[')

EDIT(2015年1月20日):這裏是一個很好的資源,雖然沒有具體到SQL Server,詳細描述各種類型的SQL注入的:https://www.owasp.org/index.php/Testing_for_SQL_Injection_(OTG-INPVAL-005)

下面的文章涉及上述一個。這一個特定於SQL Server,但在整體安全性方面更一般。有幾個與SQL注入相關的部分:
https://www.owasp.org/index.php/Testing_for_SQL_Server

+0

謝謝!我正在尋找的答案的類型。 – piaste 2014-12-02 19:12:15

3

(刀片圍繞打破消毒和逃離這裏的危險言論。見marc_s的評論。)

你在這裏提出什麼是微軟的SQL Server管理對象(SMO)使用同樣的方法。這些都是.NET DLL,可以使用反編譯器進行檢查。例如:

internal static string MakeSqlString(string value) 
{ 
    StringBuilder builder = new StringBuilder(); 
    builder.Append("N'"); 
    builder.Append(EscapeString(value, '\'')); 
    builder.Append("'"); 
    return builder.ToString(); 
} 

public static string EscapeString(string value, char escapeCharacter) 
{ 
    StringBuilder builder = new StringBuilder(); 
    foreach (char ch in value) 
    { 
     builder.Append(ch); 
     if (escapeCharacter == ch) 
     { 
      builder.Append(ch); 
     } 
    } 
    return builder.ToString(); 
} 

因此根據微軟的是,簡單地做一個Replace("'", "''")就足夠了。我確定這不僅僅是實習生代碼,而是爲了安全而進行審計。由於SDL,他們總是這樣做。

還請注意,這段代碼似乎是由使用Unicode(見N前綴)工作。顯然,這也是Unicode安全的。

在一個比較主觀的注:我不逃避T-SQL字符串文字就是這樣的,如果我不得不這樣做。我相信這種方法。

2

這是在.NET
我現在發現的問題是標籤的TSQL而不是.NET

馬克暗示,你可以用Unicode或十六進制表示欺騙它。 我測試過,無論是unicode還是hex都在.NET中愚弄它。

至於用適當數量的撇號愚弄它。 如果你總是用兩個替換一個,我看不出一個合適的數字如何欺騙它。

u0027和x0027是撇號,它是有兩個單引號
2018年至2019年更換的左,右的報價和SQL只是它們當作文字

string badString = "sql inject \' bad stuff here hex \x0027 other bad stuff unicode \u0027 other bad stuff left \u2018 other bad stuff right \u2019 other bad stuff"; 
    System.Diagnostics.Debug.WriteLine(badString); 
    System.Diagnostics.Debug.WriteLine(SQLclean(badString)); 
} 
public string SQLclean(string s) 
{ 
    string cleanString = s.Replace("\'", "\'\'"); 
    return "N\'" + cleanString + "\'"; 
} 

我認爲參數是一個更好的做法

相關問題