- You could use a read only user, this would at least block any updates.
- Look for keywords that look suspicious to you: INSERT, UPDATE, etc.
- Use third-party libraries like this
Here is the good bunch of anti injections techniques.
Question
I have a situation where I must use dynamic SQL as its appearing difficult to use parameters.
The query I will execute dynamically is as below. What is the best way to validate the string in @sql for malicious SQL? I need to allow valid strings like 'CountryId = 23' but not allow strings like 'delete from Countries'. I do not want everything to be NOT ALLOWED.
I am using C# to run this query against SQL Server 2008 R2.
Perhaps, I could validate at SQL level or at C# level, but I am unsure which would be better.
SET @sql = 'SELECT * from Customers
where ' + @filterExpression +
' order by ' + @sortExpression;
EXEC sp_executesql @sql
UPDATE: Maxim's answer seems to be the best for situations where you must use dynamic SQL, though dynamic SQL like the code I have in this post should be avoided as much as possible.
I came up with some validation on the variable @filterExpression in T-SQL to validate for malicious SQL code, which may still miss some malicious cases, but here is the T-SQL I came up with.
IF PATINDEX('%DELETE %', @filterExpression ) > 0
OR PATINDEX('%SELECT %FROM%', @filterExpression ) > 0
OR PATINDEX('%;%', @filterExpression ) > 0
OR PATINDEX('%DROP %', @filterExpression ) > 0
OR PATINDEX('%CREATE %', @filterExpression ) > 0
OR PATINDEX('%TRUNCATE %', @filterExpression ) > 0
OR PATINDEX('%sys%', @filterExpression ) > 0
OR PATINDEX('%INDEX %', @filterExpression ) > 0
OR PATINDEX('%UPDATE %', @filterExpression ) > 0
OR PATINDEX('%INSERT %', @filterExpression ) > 0
OR PATINDEX('%EXEC %', @filterExpression ) > 0
OR PATINDEX('%EXECUTE %', @filterExpression ) > 0
OR PATINDEX('%CAST%', @filterExpression ) > 0
OR PATINDEX('%DECLARE %', @filterExpression ) > 0
OR PATINDEX('%CONVERT%', @filterExpression ) > 0
BEGIN
RETURN;
END