龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

ASP与ASP.NET中的SQL注入及防范

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
什么是SQL注入? SQL资料隐码攻击 (SQL injection)又称为 隐码攻击 、 SQL注入 等,是发生于应用程式之数据库层的安全漏洞。简而言之,是在输入的资料字串之中夹带SQL指令,在设计不良

什么是SQL注入?

SQL资料隐码攻击(SQL injection)又称为隐码攻击SQL注入等,是发生于应用程式之数据库层的安全漏洞。简而言之,是在输入的资料字串之中夹带SQL指令,在设计不良的程式当中忽略了检查,那么这些夹带进去的指令就会被数据库服务器误认为是正常的SQL指令而执行,因此招致到破坏。

SQL 注入攻击是比较常见的方式:
例如这么一张表格:

  1. CREATE TABLE [users] (   
  2.     [userid] [varchar] (16) COLLATE Chinese_PRC_CI_AS NOT NULL ,   
  3.     [password] [varchar] (8) COLLATE Chinese_PRC_CI_AS NOT NULL ,   
  4. ON [PRIMARY]   
  5. GO  

假如代码是这样的:

  1. <%   
  2. userid = TRIM(Request("uid"))   
  3.   
  4. Set Conn = Server.CreateObject("ADODB.Connection")   
  5. Conn.Open "PROVIDER=SQLOLEDB;UID=test;PWD=test;DATABASE=test"  
  6.   
  7. Set RS = Server.CreateObject("ADODB.Recordset")   
  8. RS.Open "SELECT * FROM users WHERE userid='"&userid"'", Conn   
  9.   
  10. while not RS.EOF   
  11.     Response.Write RS("userid")","&RS("password")"<br>"  
  12.     RS.Movenext   
  13. wend   
  14.   
  15. RS.Close   
  16. Conn.Close   
  17.   
  18. Set RS = nothing   
  19. Set Conn = nothing   
  20. %>  

那么通过

  1. http://127.0.0.1:81/test.asp?uid=guest' or '1'='1  

这种方式调用将显示users表里所有用户。

ASP和ASP.NET的安全防范

(1) 过滤所有非法字符
例如:字符串过滤"'","--",";" 等字符,数字型变量使用CLng, CInt 进行一次强制转换。

(2)用Command对象
例如:

  1. <%   
  2. userid = TRIM(Request("uid"))   
  3.   
  4. Set Conn = Server.CreateObject("ADODB.Connection")   
  5. Conn.Open "PROVIDER=SQLOLEDB;UID=test;PWD=test;DATABASE=test"  
  6.   
  7. Set Cmd = Server.CreateObject("ADODB.Command")   
  8.   
  9. Cmd.ActiveConnection = Conn   
  10. Cmd.CommandType = adCmdText   
  11. Cmd.CommandText = "SELECT * FROM users WHERE userid = ?"  
  12. Cmd.Parameters.Refresh   
  13. Cmd("Param1") = userid   
  14.   
  15. Set RS = Cmd.Execute   
  16.   
  17. while not RS.EOF   
  18.     Response.Write RS("userid")","&RS("password")"<br>"  
  19.     RS.Movenext   
  20. wend   
  21.   
  22. RS.Close   
  23. Conn.Close   
  24.   
  25. Set RS = nothing   
  26. Set Cmd = nothing   
  27. Set Conn = nothing   
  28. %>  

ASP版本


但对于类似包含子查询的复杂语句,如:

  1. Cmd.CommandText = "SELECT * FROM users WHERE userid=? OR userid IN (SELECT userid FROM customer WHERE username=?)"  
  2. Cmd.Parameters.Refresh   
  3. Cmd("Param1") = userid   
  4. Cmd("Param2") = username  

这种方式执行时会显示如下错误信息:

无法从带子选择的查询 SQL 语句中获得参数信息。在准备命令前,请设置参数信息。

需要采用如下方式:

  1. Cmd.CommandText = "SELECT * FROM users WHERE userid=? OR userid IN (SELECT userid FROM customer WHERE username=?)"  
  2. Cmd.Parameters.Append(Cmd.CreateParameter("userid", adVarChar, adParamInput, 16, userid))   
  3. Cmd.Parameters.Append(Cmd.CreateParameter("username", adVarChar, adParamInput, 16, username))   

(3) 采用存储过程
例如,建立存储过程GetUsers:

  1. CREATE  PROCEDURE GetUsers   
  2. (   
  3.     @userid varchar(16),   
  4.     @username varchar(16)   
  5. )   
  6.   
  7. AS  
  8.   
  9. SET NOCOUNT ON  
  10.   
  11. /**//* 选择返回的记录集 */   
  12.   
  13. SELECT * FROM users WHERE userid=@userid   
  14.           OR userid IN (SELECT userid FROM userdetails WHERE username=@username)   
  15.   
  16. GO  

调用代码如下:

  1. <%   
  2. userid = TRIM(Request("uid"))   
  3. username = TRIM(Request("username"))   
  4.   
  5. Set Conn = Server.CreateObject("ADODB.Connection")   
  6. Conn.Open "PROVIDER=SQLOLEDB;UID=test;PWD=test;DATABASE=test"  
  7.   
  8. Set Cmd = Server.CreateObject("ADODB.Command")   
  9.   
  10. Cmd.ActiveConnection = Conn   
  11. Cmd.CommandType = adCmdStoredProc   
  12. Cmd.CommandText = "GetUsers"  
  13. Cmd.Parameters.Append(Cmd.CreateParameter("userid", adVarChar, adParamInput, 16, userid))   
  14. Cmd.Parameters.Append(Cmd.CreateParameter("username", adVarChar, adParamInput, 16, username))   
  15.   
  16. Set RS = Cmd.Execute   
  17.   
  18. while not RS.EOF   
  19.     Response.Write RS("userid")","&RS("password")"<br>"  
  20.     RS.Movenext   
  21. wend   
  22.   
  23. RS.Close   
  24. Conn.Close   
  25.   
  26. Set RS = nothing   
  27. Set Cmd = nothing   
  28. Set Conn = nothing   
  29. %>  

ASP.NET版本

  1. SqlConnection Conn = new SqlConnection("SERVER=127.0.0.1;UID=sa;PWD=123456;DATABASE=mydb");   
  2. SqlCommand Cmd = new SqlCommand();   
  3.   
  4. try  
  5. {   
  6.     Conn.Open();   
  7.     Cmd.Connection = Conn;   
  8.     Cmd.CommandType = CommandType.Text;   
  9.     Cmd.CommandText = "SELECT * FROM users WHERE userid = @userid";   
  10.   
  11.     Cmd.Parameters.Add("@userid", SqlDbType.VarChar, 16).Value = "vckbase";   
  12.   
  13.     SqlDataReader myReader;   
  14.     myReader = Cmd.ExecuteReader();   
  15.        
  16.     if(myReader.Read())   
  17.     {   
  18.         Console.Write(myReader["username"].ToString());   
  19.     }   
  20.     else  
  21.         Console.Write("读取失败");   
  22.   
  23.     myReader.Close();   
  24. }   
  25. catch(SqlException SqlEx)   
  26. {   
  27. }   
  28.   
  29. finally  
  30. {   
  31.     Conn.Close();   
  32. }   
精彩图集

赞助商链接