欢迎投稿

今日深度:

参数化查询为什么能够防止SQL注入(1)(2)

在这篇文章中有这么一段:

image

这里作者有一句话:”不过这种写法和直接拼SQL执行没啥实质性的区别

任何拼接SQL的方式都有SQL注入的风险,所以如果没有实质性的区别的话,那么使用exec 动态执行SQL是不能防止SQL注入的。

比如下面的代码:

  1. private static void TestMethod()  
  2. {  
  3.     using (SqlConnection conn = new SqlConnection(connectionString))  
  4.     {  
  5.         conn.Open();  
  6.         SqlCommand comm = new SqlCommand();  
  7.         comm.Connection = conn;  
  8.         //使用exec动态执行SQL   
  9.         //实际执行的查询计划为(@UserID varchar(max))select * from Users(nolock) where UserID in (1,2,3,4)  
  10.         //不是预期的(@UserID varchar(max))exec('select * from Users(nolock) where UserID in ('+@UserID+')')      
  11.         comm.CommandText = "exec('select * from Users(nolock) where UserID in ('+@UserID+')')";  
  12.         comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.VarChar, -1) { Value = "1,2,3,4" });  
  13.         //comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.VarChar, -1) { Value = "1,2,3,4); delete from Users;--" });  
  14.         comm.ExecuteNonQuery();  
  15.     }  

执行的SQL 如下:

  1. exec sp_executesql N'exec(''select * from Users(nolock) where UserID in (''+@UserID+'')'')',N'@UserID varchar(max) ',@UserID='1,2,3,4' 

D25E99E053D549AF955518AD0A320259

可以看到SQL语句并没有参数化查询。

如果你将UserID设置为”

1,2,3,4); delete from Users;—-

”,那么执行的SQL就是下面这样:

  1. exec sp_executesql N'exec(''select * from Users(nolock) where UserID in (''+@UserID+'')'')',N'@UserID varchar(max) ',@UserID='1,2,3,4); delete from Users;--' 

不要以为加了个@UserID 就代表能够防止SQL注入,实际执行的SQL 如下:

3C50EFE68418448496BAC7773067AB6F

任何动态的执行SQL 都有注入的风险,因为动态意味着不重用执行计划,而如果不重用执行计划的话,那么就基本上无法保证你写的SQL所表示的意思就是你要表达的意思。

这就好像小时候的填空题,查找密码是(____) 并且用户名是(____)的用户。

不管你填的是什么值,我所表达的就是这个意思。

最后再总结一句:因为参数化查询可以重用执行计划,并且如果重用执行计划的话,SQL所要表达的语义就不会变化,所以就可以防止SQL注入,如果不能重用执行计划,就有可能出现SQL注入,存储过程也是一样的道理,因为可以重用执行计划。


www.htsjk.Com true http://www.htsjk.com/shujukujc/18742.html NewsArticle 在这篇文章中有这么一段: 这里作者有一句话: 不过这种写法和直接拼SQL执行没啥实质性的区别 任何拼接SQL的方式都有SQL注入的风险,所以如果没有实质...
评论暂时关闭