I can't get away without writing some dynamic sql conditions in a part of my system (using Postgres).
My question is how best to avoid SQL Injection with the method I am currently using.
EDIT (Reasoning): There are many of columns in a number of tables (a number which grows (only) and is maintained elsewhere). I need a method of allowing the user to decide which (predefined) column they want to query (and if necessary apply string functions to). The query itself is far too complex for the user to write themselves, nor do they have access to the db. There are 1000's of users with varying requirements and I need to remain as flexible as possible - I shouldn't have to revisit the code unless the main query needs to change - Also, there is no way of knowing what conditions the user will need to use.
I have objects (received via web service) that generates a condition (the generation method is below - it isn't perfect yet) for some large sql queries.
The _FieldName is user editable (parameter name was, but it didn't need to be) and I am worried it could be an attack vector. I put double quotes (see quoted identifier) around the field name in an attempt to sanitize the string, this way it can never be a key word. I could also look up the field name against a list of fields, but it would be difficult to maintain on a timely basis.
Unfortunately the user must enter the condition criteria, I am sure there must be more I can add to the sanatize method? and does quoting the column name make it safe? (my limited testing seems to think so).
an example built condition would be "AND upper(brandloaded.make) like 'O%' and upper(brandloaded.make) not like 'OTHERBRAND'" ...
Any help or suggestions are appreciated.
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