我听说"每个人"都在使用参数化SQL查询来防止SQL注入攻击,而不必为每一条用户输入进行操作.
你怎么做到这一点?使用存储过程时是否自动获得此信息?
所以我理解这是非参数化的:
cmdText = String.Format("SELECT foo FROM bar WHERE baz = '{0}'", fuz)
这会参数化吗?
cmdText = String.Format("EXEC foo_from_baz '{0}'", fuz)
或者我是否需要做更广泛的事情以保护自己免受SQL注入?
With command
.Parameters.Count = 1
.Parameters.Item(0).ParameterName = "@baz"
.Parameters.Item(0).Value = fuz
End With
除安全考虑因素外,使用参数化查询还有其他优点吗?
更新:这篇伟大的文章与格罗托克的一个问题相关联. http://www.sommarskog.se/dynamic_sql.html
您的EXEC示例不会参数化.您需要参数化查询(在某些圈子中准备好的语句)以防止这样的输入造成损害:
'; DROP TABLE栏; -
试着把它放在你的fuz变量中(或者,如果你重视吧台,那就不要).更加微妙和有害的查询也是可能的.
以下是如何使用Sql Server执行参数的示例:
Public Function GetBarFooByBaz(ByVal Baz As String) As String
Dim sql As String = "SELECT foo FROM bar WHERE baz= @Baz"
Using cn As New SqlConnection("Your connection string here"), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Baz
Return cmd.ExecuteScalar().ToString()
End Using
End Function
存储过程有时会被用于防止SQL注入.但是,大多数情况下,您仍然需要使用查询参数调用它们,否则它们无法帮助您.如果您专门使用存储过程,那么您可以为应用程序用户帐户关闭SELECT,UPDATE,ALTER,CREATE,DELETE等权限(除了EXEC之外的所有内容),并以此方式获得一些保护.
绝对是最后一个,即
或者我是否需要做更广泛的......?(是
cmd.Parameters.Add()
)
参数化查询有两个主要优点:
安全性:这是避免SQL注入漏洞的好方法
性能:如果您经常使用不同的参数调用相同的查询,则参数化查询可能允许数据库缓存您的查询,这是性能增益的重要来源.
额外:您不必担心数据库代码中的日期和时间格式问题.同样,如果您的代码将在具有非英语语言环境的计算机上运行,则不会出现小数点/小数点逗号的问题.
您想要使用最后一个示例,因为这是唯一真正参数化的示例.除了安全问题(这可能比您想象的要普遍得多)之外,最好让ADO.NET处理参数化,因为您无法确定传入的值是否需要单引号而不检查Type
每个参数.
[编辑]这是一个例子:
SqlCommand command = new SqlCommand( "select foo from bar where baz = @baz", yourSqlConnection ); SqlParameter parameter = new SqlParameter(); parameter.ParameterName = "@baz"; parameter.Value = "xyz"; command.Parameters.Add(parameter);