An important aspect to remember about SQL injection is that, if at all possible, you should never embed user-supplied values directly in your SQL. This does not mean that you cannot use dynamic sql (although it definitely makes things easier if you don't), but sometimes it becomes more dangerous.
In your specific example, you can save the parameterization of everything except @field_name . This, unfortunately, has to be built directly into SQL; everything else can be passed as a parameter again, so there is no need to worry about their contents.
The safest thing you can do in this particular example is the following:
if(exists (select 1 from INFORMATION_SCHEMA.Columns where TABLE_NAME = 'Table' and TABLE_SCHEMA = 'dbo' and COLUMN_NAME = @fieldName)) begin DECLARE @sql nvarchar(1000) SET @sql = 'UPDATE dbo.TABLE '+ 'SET ' + QUOTENAME(@field_name) + ' =@value ' + 'WHERE company_id=@company _id AND '+ ' id=@id ' exec sp_executesql @sql,N'@id bigint, @company_id uniqueidentifier, @value nvarchar(50)',@id,@company_id,@value end
This does two things:
- It checks that there is actually a column with that name in the table. If the user inserted any other SQL statements into this field, this check would fail and the statement would not be executed. You can also raise
raiseerror to report an error, but I will leave this exercise to you. - It encloses the field name in square brackets so that field names containing spaces or reserved words will not violate the operator. This may not be a problem for you, but it is always a good practice if you are creating SQL yourself.
source share