从C#代码中避免在MSSQL Server上注入SQL的算法?

什么是避免在C#.net平台上进行SQL注入的最佳方法。

如果有的话,请发布C#实现。

我们可以做的十件事是安全的(没有一个会做到这一切。)

  1. 采纳“所有数据都是邪恶的”概念。 所有数据,甚至存储在数据库或我们的文件系统中的数据都是可疑的。 不仅仅是我们防火墙外的应用程序输入的数据,如查询字符串,表单字段,cookie等。任何东西都可以用来破坏系统。

  2. 不要依赖于javascript或html字段长度的客户端validation,甚至不依赖于使用客户端validation的服务器端Web API。 使用它来提高可用性,但不要依赖它作为唯一的保护。 了解如NET工作的API提供的validation器。 不要把它们视为理所当然。 他们有各种各样的方法。

  3. 进行正匹配以捕获所有数据。如果数据匹配正则表达式的字符范围,那么它没关系。 这不允许奇怪的unicode字符进入我们的数据库,可能会在sql中意外地划分某些内容或者创建其他问题,如同形XSS /网络钓鱼攻击。 相反,负匹配需要所有不良字符的列表,这些字符似乎一直在增长。 这是一个糟糕的方法。 积极匹配更好。 我们拒绝不良数据,不消毒或逃避它。

  4. 如果可能,请考虑使用“更新”,“删除”,“删除”,“选择”,“更改”等过滤,标记或捕获字符串数据。考虑到字符串的性质,这可能无法实现。 “1212 Lemondrop Ln”,“Waltersburg,PA”和“Table Rock,NE”是有效的地址字段。 对与其中任何一个匹配的字段运行所有表数据的每日扫描可能会发现延迟的攻击或漏洞。 此外,当数据进入时,也可以使用日志记录,IP禁止,电子邮件警报等。

  5. 尽可能使用存储过程和/或参数化查询。 在db客户端代码和sql中都避免使用动态sql。 (避免使用带有存储过程中外部部分的动态代码的exec语句!!!)参数化将转义字符串终止符,如撇号,捕获字段长度和类型检查。 我们不能总是依赖提供参数化的API来完善,但它们是由比我们大多数人更了解数据库特性的人编写的。

  6. 确保世界可读/可执行的Web目录中没有杂散代码。 如果它不是活动站点的一部分,请将其存档到安全的位置并从公共视图中删除它。 未使用的存储过程也是如此。

  7. 及时了解数据库API。 在某些API中执行SQL语句的某些方法并不像其他API那样安全。

  8. 使用单向加密安全地存储密码。 这样,用户名和密码的表转储仍然应该让人们离开。

  9. 以通常的方式强化服务器。 例如,如果可能,请为数据库表提供最小权限。 将Web服务器数据库帐户的访问权限严格限制在相关表中。 尽可能使用只读。 创建多个帐户,在公共和内部/可信流量的访问权限之间划分。

  10. 优雅地捕获错误。 这适用于所有代码,而不仅仅是使用数据库的代码。 然而,SQL注入攻击特别依赖于错误消息,因此希望尽可能多地隐藏公共数据库。 始终编​​写以异乎寻常的方式处理exception或空数据集的代码,以尽可能少地揭示我们正在使用的数据库类型,字段在表中的内容,或者我们运行的查询类型。 记录服务器上的错误。 即使在非数据库代码中,最好还是保持第三方组件,文件夹结构,我们可能正在运行的其他服务的安静等等。尽可能少地给予恶意用户信息是保持他们无能为力的关键。

#11,总是重新访问/修改此列表。 始终保持最新状态。 主动。 将其作为前期优先事项和要求,而不是经过深思熟虑。

不需要算法 – 只是不要使用字符串连接来构建SQL语句。 请改用SqlCommand.Parameters集合。 这样做了所有必要的值转义(例如替换' with '' )并确保命令是安全的,因为其他人(即Microsoft)已完成所有测试。

例如,调用存储过程:

 using (var connection = new SqlConnection("...")) using (var command = new SqlCommand("MySprocName", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@Param1", param1Value); return command.ExecuteReader(); } 

此技术也适用于内联SQL语句,例如

 var sql = "SELECT * FROM MyTable WHERE MyColumn = @Param1"; using (var connection = new SqlConnection("...")) using (var command = new SqlCommand(sql, connection)) { command.Parameters.AddWithValue("@Param1", param1Value); return command.ExecuteReader(); }