我使用的是一个需要SQL字符串的API。我接受用户输入,将其转义并将其传递给API。用户输入非常简单。它要求列值。像这样:
string name = userInput.Value;
然后我构造一个SQL查询:
string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
name.replace("'", "''"));
这样安全吗?如果不是,是否有一个简单的库函数可以使列值安全:
string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
SqlSafeColumnValue(name));
API使用SQLServer作为数据库。
答案 0 :(得分:114)
由于使用SqlParameter不是一个选项,只需在字符串文字中替换'with''(两个单引号,而不是一个双引号)。就是这样。
对于潜在的贬低者:重新阅读问题的第一行。 “使用参数”也是我的直觉反应。
编辑:是的,我知道SQL注入攻击。如果您认为这种引用容易受到引用,请提供一个有效的反例。我认为不是。答案 1 :(得分:0)
我正在使用动态sql(我可以听到射击小队加载他们的步枪)用于搜索功能,但每当用户搜索姓氏为“O'Reilly”的人时,它就会中断。
我设法解决了一个解决方法(读“黑客”):
在sql中创建了一个标量值函数,用两个单引号替换单引号,有效地转义了违规的单引号,所以
“......喜欢'%O'Reilly%'和......”
变
“......喜欢'%O''Reilly%'并且......”
每当我怀疑字段可能包含单引号字符时,就会从sql中调用此函数,即:firstname,lastname。
CREATE FUNCTION [dbo].[fnEscapeSingleQuote]
(@StringToCheck NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @Result NVARCHAR(MAX)
SELECT @Result = REPLACE(@StringToCheck, CHAR(39), CHAR(39) + CHAR(39))
RETURN @Result
END
不是很优雅或高效,但是当你处于紧张状态时它会起作用。
答案 2 :(得分:0)
当需要在短时间内解决大量ad hoc sql中的问题时,可能希望替换'with'而不是参数化,同时将破损和最小测试的风险降至最低。
答案 3 :(得分:0)
最好使用sql参数,但是你有2300个参数限制查询。在大多数情况下,这将是绰绰有余的。但是在极少数情况下,当你超过这个限制时,我认为这是一个选择。
答案 4 :(得分:0)
SqlCommand和Entity Framework使用exec sp_executesql...
。
因此,可能存在一种原始字符串的替代方法,其中包含您自己的转义模式。使用SqlCommand,您在技术上使用参数化查询,但是您绕过了底层SQL代码的ADO.Net抽象。
因此,虽然您的代码不会阻止SQL注入,但最终的答案是sp_executesql而不是SqlCommand。
话虽如此,我确信生成一个使用sp_executesql的SQL注入证明字符串有特殊的处理要求。
请参阅:How to return values from a dynamic SQL Stored Procedure to the Entity Framework?
答案 5 :(得分:-1)
简单:
const string sql = "SELECT * FROM SOME_TABLE WHERE Name = @name";
并添加@name
参数值:
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("@name", name);
答案 6 :(得分:-11)
如果您需要为MSSQL查询转义字符串,请尝试:
System.Security.SecurityElement.Escape(Value)