我有一个生成查询字符串的实用程序,但是静态代码分析器(和我的同事)抱怨,因为存在“ SQL注入攻击” 的风险。
这是我的C#代码
public static string[] GenerateQueries(string TableName, string ColumnName)
{
return new string[] {
"SELECT * FROM " + TableName,
"SELECT * FROM " + TableName + " WHERE 1=2",
"SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = @id",
"SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = IDENT_CURRENT('" + TableName + "')",
"SELECT * FROM " + TableName + " WHERE [" + ColumnName + "] = @value"
};
}
在代码中,我总是将其称为仅,它带有常量字符串,例如
var queryList = GenerateQueries("Person", "Name");
是否有任何方法可以重写此功能,使其“安全”?例如,如果我使用C而不是C#,则可以编写宏来安全地生成字符串。
目前,我唯一的选择是复制/粘贴这个SELECT语句块用于每个单个表,这很丑陋,而且维护负担大。 / p>
复制/粘贴确实是我唯一的选择吗?
编辑:
谢谢您的答复,特别是威廉·利德(William Leader)。现在我看到我的问题是错误的。我不仅要串联查询字符串,还要将它们存储在 变量 中。唯一正确的方法是使用常量(例如,
)构造SqlDataAdapter
var adapter = new SqlDataAdapter("SELECT * FROM PERSON");
没有其他选择。所以是的,会有很多复制/粘贴。我开始后悔没有使用EF。
答案 0 :(得分:3)
起初我很震惊,但是经过反思,这与在代码中已经有一个如下所示的SQL语句没什么不同:
"SELECT * FROM Person"
我们一直在做这种事情。
这里有一个重要的警告。只有在 if 可以控制函数调用方式的情况下,这种情况才成立。因此,如果此方法是某个地方的数据层类的 private 成员,则可能可以。但是我也想知道这真的有用吗。似乎您没有为编写查询而节省多少。
此外,养成忽略静态分析工具的习惯也是不好的。有时,他们给您的东西您只是知道是错的,但是您还是要对其进行更改,以使他们做发现重要的东西时,您不会无视它。
答案 1 :(得分:0)
您的代码分析器告诉您的是,您很可能应该使用某些参数来调用过程,而不是通过网络发送SQL。
无论您是否使用宏来生成SQL语句,都不会一,而就,如果您通过网络发送原始SQL,则您很容易受到 SQL注入攻击
将SQL命令发送到未授权的端点。如果我们启动网络数据包嗅探器,则可以看到您已将数据库配置为允许发送SQL命令,因此我们可以将非法SQL注入系统中
您仍然可以依靠单个过程来调用更新,但是如果您选择移至过程,为什么要这么做?
编辑以提供示例
Byte
或者是特定于表的过程
create PROC sp_CommonSelectFromTableProc @tableName varchar(32)
AS
-- code to check the tableName parameter does not contain SQL and/or is a valid tableName
-- your procedure code here will probable use
-- exec mydynamicSQLString
-- where mydynamicSQLString is constructed using @tableName
END;
要记住的重要一点是, SQL注入独立于基础应用程序所使用的技术 。
当应用程序包含诸如
之类的构造时,这是公开的create PROC sp_SelectFromSpecificTableProc
AS
SELECT * FROM SpecificTable
END;
SQL注入 必须在数据通道的两端进行寻址。
Here是了解如何缓解SQL注入攻击的一个很好的起点