Jie

心若无尘,一花一世界,一鸟一天堂;心若静,已如涅磐,风声物语,皆可成言.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

防止SQL注入攻击

Posted on 2008-05-30 13:27  JieNet  阅读(458)  评论(0编辑  收藏  举报

 防止SQL注入攻击。 注:内容来自MSDN

代码1-1
private void cmdLogin_Click(object sender, System.EventArgs e) {
    
string strCnx = 
     
"server=localhost;database=northwind;uid=sa;pwd=;";
     SqlConnection cnx 
= new SqlConnection(strCnx);

    cnx.Open();

    
//This code is susceptible to SQL injection attacks.
    string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
     txtUser.Text 
+ "' AND Password='" + txtPassword.Text + "'";
    
int intRecs;

    SqlCommand cmd 
= new SqlCommand(strQry, cnx);
    intRecs 
= (int) cmd.ExecuteScalar();

    
if (intRecs>0{
        FormsAuthentication.RedirectFromLoginPage(txtUser.Text, 
false);
    }

    
else {
        lblMsg.Text 
= "Login attempt failed.";
    }


    cnx.Close();
}


 

上面这段代码容易被SQL注入攻击成功。

看一下查询语句:

    string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +

     txtUser.Text + "' AND Password='" + txtPassword.Text + "'";

如果是正常的用户登录则查询语句会是如下这种形式:

SELECT Count(*) FROM Users WHERE UserName='Paul' AND Password='password'

但是,如果有人输入的用户名是  ' Or 1=1 –  则查询语句就变成了:

SELECT Count(*) FROM Users WHERE UserName='' Or 1=1

这样的话 1=1 地球都知道这结果是True

如何防范?

把代码1-1写成代码1-2(推荐)或1-3的形式,看看就明白其中的道理了。

//代码1-2存储过程参数(强烈推荐使用存储过程)
private void cmdLogin_Click(object sender, System.EventArgs e) {
    
string strCnx = 
        ConfigurationSettings.AppSettings[
"cnxNWindBetter"];
    
using (SqlConnection cnx = new SqlConnection(strCnx))
    
{
        SqlParameter prm;

        cnx.Open();

        
string strAccessLevel;

        SqlCommand cmd 
= new SqlCommand("procVerifyUser", cnx);
        cmd.CommandType
= CommandType.StoredProcedure;

        prm 
= new SqlParameter("@username",SqlDbType.VarChar,50);
        prm.Direction
=ParameterDirection.Input;
        prm.Value 
= txtUser.Text;
        cmd.Parameters.Add(prm);

        prm 
= new SqlParameter("@password",SqlDbType.VarChar,50);
        prm.Direction
=ParameterDirection.Input;
        prm.Value 
= txtPassword.Text;
        cmd.Parameters.Add(prm);            

        strAccessLevel 
= (string) cmd.ExecuteScalar();

        
if (strAccessLevel.Length>0{
            FormsAuthentication.RedirectFromLoginPage(txtUser.Text, 
false);
        }

        
else {
            lblMsg.Text 
= "Login attempt failed.";
        }

    }

}



//代码1-3 命令参数
private void cmdLogin_Click(object sender, System.EventArgs e) {
    
string strCnx = ConfigurationSettings.AppSettings["cnxNWindBad"];
    
using (SqlConnection cnx = new SqlConnection(strCnx))
    
{
        SqlParameter prm;

        cnx.Open();

        
string strQry = 
            
"SELECT Count(*) FROM Users WHERE UserName=@username " +
            
"AND Password=@password";
        
int intRecs;

        SqlCommand cmd 
= new SqlCommand(strQry, cnx);
        cmd.CommandType
= CommandType.Text;

        prm 
= new SqlParameter("@username",SqlDbType.VarChar,50);
        prm.Direction
=ParameterDirection.Input;
        prm.Value 
= txtUser.Text;
        cmd.Parameters.Add(prm);

        prm 
= new SqlParameter("@password",SqlDbType.VarChar,50);
        prm.Direction
=ParameterDirection.Input;
        prm.Value 
= txtPassword.Text;
        cmd.Parameters.Add(prm);            

        intRecs 
= (int) cmd.ExecuteScalar();

        
if (intRecs>0{
            FormsAuthentication.RedirectFromLoginPage(txtUser.Text, 
false);
        }

        
else {
            lblMsg.Text 
= "Login attempt failed.";
        }

    }

}