2017-08-22 11 views
2

C#から文字列連結を使用してSQL Server 2016スクリプトを作成する必要があります(このスクリプトはADO.NETを介して実行されます)。スクリプトは設定スクリプトのほうが多く、パラメータ化できない文が含まれているため、私は通常行うクエリパラメータを使用できません。Escapeデータベースオブジェクト名

"ALTER DATABASE " + Escape(databaseName) + " ADD ..." 

は、SQLインジェクションの脆弱性ではない:

というような名前を逃れるために行くための方法は何ですか? Escapeの実装方法ただし、すべての名前の角括弧を使用していますが、これで十分ではありません。

+0

あなたが特定のチェックの変数を検証することができとにかく[]のように与えてください。 " – BugFinder

+1

@BugFinder、醜い、間違った、ひどい、そして[ここに多くの形容詞を挿入]、それは完全に*合法です* SQL Serverで' ['というテーブルを持っている=( – Rob

+0

本当ですが、あなたのアプリのために:D – BugFinder

答えて

2

これを実現するにはQUOTENAMEの組み込み関数を使用できます。

SQLで実行する前にC#でスクリプトを構築しているように見えますが、これを行うにはデータベースに移動するC#関数が必要になるでしょう結果値をDictionary<string, string>に保存して、既に引用されている文字列のラウンドトリップを排除します。例えば

private Dictionary<string, string> _quotedNames = new Dictionary<string, string>(); 

private string GetSqlQuotedName(string name) 
{ 
    if (!_quotedNames.ContainsKey(name)) 
    { 
     _quotedNames[name] = GetSqlQuotedNameFromSqlServer(name); 
    } 

    return _quotedNames[name]; 
} 

private string GetSqlQuotedNameFromSqlServer(string name) 
{ 
    /// Code here to use your Data access method of choice to basically execute 
    /// SELECT QUOTENAME(name) and return it 
} 

は、実際には、ちょうどSystem.Data.SqlClient名前空間のクラスを使用して、これを表示するには、ここで話をするために使用する接続文字列を与えられたこの動作を、実行するクラスですSQL Serverへ:

public class SqlNameEscaper 
{ 
    private Dictionary<string, string> _quotedNames = new Dictionary<string, string>(); 
    private string _connectionString = string.Empty; 

    public SqlNameEscaper(string connectionString) 
    { 
     _connectionString = connectionString; 
    } 

    public string GetSqlQuotedName(string name) 
    { 
     if (!_quotedNames.ContainsKey(name)) 
     { 
      _quotedNames[name] = GetSqlQuotedNameFromSqlServer(name); 
     } 

     return _quotedNames[name]; 
    } 

    private string GetSqlQuotedNameFromSqlServer(string name) 
    { 
     using (var connection = new SqlConnection(_connectionString)) 
     { 
      connection.Open(); 
      using (var command = new SqlCommand("SELECT QUOTENAME(@name)", connection)) 
      { 
       command.Parameters.AddWithValue("@name", name); 
       var result = command.ExecuteScalar(); 

       return result.ToString(); 
      } 
     } 
    } 
} 

これは、その後、これを行うことによって呼び出すことができます。

var sne = new SqlNameEscaper(@"CONNECTION_STRING_HERE"); 
var bracket = sne.GetSqlQuotedName("["); 

それとも、あなたの例のコンテキストで:

var sqlNameEscaper = new SqlNameEscaper(@"CONNECTION_STRING_HERE"); 
var text = "ALTER DATABASE " + sqlNameEscaper.GetSqlQuotedName(databaseName) + " ADD ..."; 

この非常に主題での読み取りを持つ価値がdba.stackexchange.com上の問題もあります:Should we still be using QUOTENAME to protect from injection attacks?

+0

QUOTENAMEまた、 'ADD FILE(name = ''、...)'? –

+0

@DRのように、 "parameters"にも使用できます。おそらく、あなたはd文字ocumentationは言及する。上記で提案したラッパー関数を使用している場合は、結果の文字列を任意の場所で使用することができます。 =) – Rob

関連する問題