用户根据系统的程序构造非法的参数从而导致程序执行不是程序员期望的恶意SQL语句。使用参数化或存储过程的SQL就可以避免SQL注入。
以登录为例,假如登录语句是String sql="select count(user.id) from sys_user user where user.user_name='?' and user_pwd = '?' " ,如果参数 user_name 和usre_pwd没有经过加密处理
当user_name为 英文的 ' 则会报sql错误,“引号内的字符串没有正确结束”等等。这样的错误如果给前台捕捉了,那么你的sys_user表就管不住了,当参数user_name or user_pwd 为 ' or 1=1 -- 时 ,拼成的sql语恒成立,像这样的情况就是一种比较简单的注入攻击行为,所 以最好把前台的参数,转换为一种数据库用不到的符号或者字符串(不是相关符号或关键字),比如,将英文的符号转成中文。
例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;namespace sql注入漏洞攻击
{
public partial class login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{ }
protected void btnLogin_Click(object sender, EventArgs e)
{
string constr = "data source=.\\SQLEXPRESSPC;initial catalog=UserDB1;user id=sa;password=admin";
using (SqlConnection con = new SqlConnection(constr))
{
//string sql = string.Format("select count(*) from T_Users where UserName='{0}'and Password='{1}'",txtUserName.Text.Trim(),txtPassword.Text);
//以上这种拼接sql语句的方法有sql注入漏洞攻击的问题,如jk' or 1=1--
//如果避免注入漏洞攻击呢?使用参数的方法或存储过程的方法
//参数方法
string sql = "select count(*) from T_Users where UserName=@UserName and Password=@password";
using (SqlCommand cmd = new SqlCommand(sql,con))
{ con.Open();
//方法1
//在数据服务端执行sql语句前需要告诉他@userName,@Password是谁
//cmd.Parameters.AddWithValue("@UserName ", txtUserName.Text.Trim());
//cmd.Parameters.AddWithValue("@password", txtPassword.Text.Trim());
//方法2
//(1)每一个参数都是一个参数对象
SqlParameter p1 = new SqlParameter("@UserName ", txtUserName.Text.Trim());
cmd.Parameters.Add(p1); SqlParameter p2 = new SqlParameter("@password", txtPassword.Text.Trim());
cmd.Parameters.Add(p2); //(2)很多情况下参数的个数很多p1...p9,用数组的方式来做
SqlParameter[] pms = new SqlParameter[] {
new SqlParameter("@UserName ", txtUserName.Text.Trim()),
new SqlParameter("@password", txtPassword.Text.Trim())
};
cmd.Parameters.AddRange(pms); //通过监视发现ADO的参数替换的方法避免了漏洞攻击,他通过 存储过程实现了把输入的任何字符串作为字符串处理的形式
//在sql中,吧'单引号转移为字符串的方法是前面再加一个单引号
//在sql中的参数都是以@开始的
int r =Convert.ToInt32(cmd.ExecuteScalar());//把SQL语句送到数据服务器端执行
con.Close();//可以提前关闭连接,提高效率
if (r > 0)
{
Response.Write("登陆成功!");
}
else
{
Response.Write("登陆失败");
}
}
}
}
}
}
在查询语句加上@username和@password这样的参数,然后再为参数赋值,利用这样的方法即可以防止漏洞,现在登录的时候再在password里输入jk' or 1=1--时不会登录成功,这样就保证了数据的安全性
小结:参数查询能够安全高效的对sql进行条件查询,所以在以后的开发工程中,尽量使用参数化的sql语句,防止注入漏洞的发生。