6

システムの一部に (Postgres を使用して) いくつかの動的な SQL 条件を記述せずにはいられません。

私の質問は、現在使用している方法で SQL インジェクションを回避する最善の方法です。

EDIT(推論):多くのテーブルに多くの列があります((のみ)成長し、他の場所で維持される数)。ユーザーが照会する (事前定義された) 列を決定できるようにする方法が必要です (必要に応じて、文字列関数を適用します)。クエリ自体は複雑すぎて、ユーザーが自分で書くことも、データベースにアクセスすることもできません。さまざまな要件を持つ何千人ものユーザーがいて、可能な限り柔軟に対応する必要があります。メインのクエリを変更する必要がない限り、コードを再検討する必要はありません。また、ユーザーが必要とする条件を知る方法もありません。使用する。

いくつかの大規模なSQLクエリの条件を生成するオブジェクト(Webサービスを介して受信)があります(生成方法は以下にあります-まだ完全ではありません)。

これ_FieldNameはユーザーが編集可能で (パラメーター名は編集可能でしたが、そうである必要はありませんでした)、攻撃ベクトルになる可能性があるのではないかと心配しています。文字列をサニタイズするために、フィールド名を二重引用符 ( quoted identifier を参照) で囲みます。この方法では、決してキーワードにはなりません。フィールドのリストに対してフィールド名を検索することもできますが、タイムリーに維持することは困難です。

残念ながら、ユーザーは条件基準を入力する必要があります。サナタイズ メソッドに追加できる条件が他にもあるはずです。列名を引用すると安全になりますか? (私の限られたテストではそう思われるようです)。

構築された条件の例は、「AND upper(brandloaded.make) like 'O%' and upper(brandloaded.make) not like 'OTHERBRAND'」 ...

ヘルプや提案をいただければ幸いです。

Public Function GetCondition() As String
   Dim sb As New Text.StringBuilder

   'put quote around the table name in an attempt to prevent some sql injection
   'http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html
   sb.AppendFormat(" {0} ""{1}"" ", _LogicOperator.ToString, _FieldName)

   Select Case _ConditionOperator
      Case ConditionOperatorOptions.Equals
          sb.Append(" = ")

      ...

   End Select

   sb.AppendFormat(" {0} ", Me.UniqueParameterName) 'for parameter

   Return Me.Sanitize(sb)

End Function

Private Function Sanitize(ByVal sb As Text.StringBuilder) As String

   'compare against a similar blacklist mentioned here: http://forums.asp.net/t/1254125.aspx

    sb.Replace(";", "")
    sb.Replace("'", "")
    sb.Replace("\", "")
    sb.Replace(Chr(8), "")

    Return sb.ToString

End Function

Public ReadOnly Property UniqueParameterName() As String
     Get
         Return String.Concat(":" _UniqueIdentifier)
     End Get
End Property
4

3 に答える 3

8

データベースから列名を取得し、比較して、ユーザーが有効な列名を入力したことを確認できます。

于 2012-06-08T17:13:22.723 に答える
2

SQLインジェクションは、ユーザーが入力したデータがパラメーター化せずに動的クエリで使用されるために発生します。残念ながら、ユーザーが入力したデータをパラメーター化できない場合、解決策はユーザーにそのデータを入力させないことです。

考えられる回避策は、受け入れ可能な文字のホワイトリスト(ブラックリストではない)を使用することです。しかし実際には、fieldNamesのリストを取得し、ユーザーが入力したことを確認する必要があります(次に、ユーザーからのものではなく、自分のバージョンの文字列を使用します)。

ユーザーが入力したデータは常に疑わしいものであり、可能な限り避ける必要があります。

于 2012-06-09T04:36:49.783 に答える
1

One thing you could do is go ahead and create your dynamic query but put something like this as a prefix:

"IF EXISTS(SELECT * FROM sys.columns where object_id=OBJECT_ID('mytable') and name = @dynamicName)
    SELECT * FROM mytable WHERE [" + dynamicName + "] = 'Whatever your test is.'"

Yeah, it makes the query a little more expensive, but it is protected against injection.

于 2020-04-29T14:52:44.660 に答える