什么是SQL注入攻击(SQL injection)?
SQL注入攻击就是指在我们进行登录访问数据库时,由于用户登录时输入的登录名和密码等字段数据的合法性未作判断,同时利用访问时执行SQL command 语句时,数据库不会对字段的合法性做二次判断的漏洞,运用巧妙的数据库连接或判断语句,使其省去用户名和密码的验证,实现无账号密码登录程序或者网站,盗取数据库信息等行为。
简单来说就是 恶意填入查询代码,致使SQL把被篡改的原本SQL字符串当做合法参数进行查询,达到免账密登录的目的。
常见的注入攻击手段(SQL injection methods)?
SQL代码恶意注入攻击法:即利用恶意填补验证代码,使数据库在执行完你填补的代码后省去对真正验证代码的执行。
如这种代码:
userId= ‘‘1’or ‘1’=‘1’--’;
passWord = ‘‘1’or ‘1’=‘1’’;
SQL Server 在执行时,其原SQL字符串
string sql=string.Format("select * from TestSchool where ( userId = ' '' + uid +'' ' )and (passWord =' '' + pwd +'' ')");
就会变成:
string sql=string.Format("select * from TestSchool where (userId = '1' or '1'='1' --) and (passWord = '1' or '1'='1')");
那么无疑SQL字符串就被简化成了:
string sql = "select * from TestSchool ";
这样就避过了用户名和密码的验证过程,直接就读取到了数据库的所有内容,实现免密登录了。
备注:易被攻击的访问连接请参见ADO.NET访问流程详解
怎么防止SQL注入攻击呢?
SQL注入攻击是数据库安全以前常见的问题,容易导致刷库、拖库、撞库等风险,现在安防技术有:数据库漏扫、数据库加密、数据库防火墙、数据脱敏、数据库安全审计系统等成熟的技术。
如果使我们在编写的时候就把这种简单的恶意代码合法检验剔除掉,数据库就相对安全多了。下面针对讲一下,如何避免恶意代码注入攻击的预防方法:参数化查
什么是参数化查询(Parameterized Query)?
简单的来说就是设计数据库访问连接时,在Textbox等要填入数据或值的地方,先将值转换成参数,然后再使用参数来进行传值操作。这种方法是目前在设计时最有效的预防注入攻击的方法。
参数化查询方法(借用SqlParameter类对象)?
--@参数占位符
string sql = string.Format('select * from TestSchool where userId = @uid and PassWord = @pwd ');
SqlParameter p = new SqlParameter("@uid",txtuid.Text.Trim());
SqlParameter p1 = new SqlParameter("@pwd",txtpwd.Text.Trim());
SqlCommand cmd = new SqlCommand( sql,conn);
cmd.Parameters.Add(p);
cmd.Parameters.Add(p1);
sql中定义局部变量(@) ?
定义变量uid 可变字符串字段,长度为50.
declare @uid nvarchar(50);
可以发现 定义变量 需要用到@作为变量前缀。
因此在
userId = @uid
相当于
userId = 变量(@+变量名)
然后通过
SqlParameter p = new SqlParameter ("@uid",txtuid.Text.Trim());
创建参数p ,通过变量uid ,将txtuid.Text.Trim()中输入的数据保存到参数p中。
参数化查询三步曲:
第一步:
sql中创建用于接受输入框数据的变量。
string sql = string.Format('select * from TestSchool where userId = @uid and PassWord = @pwd ');
第二步:
C#中创建输入框对应的参数,包括参数对象、参数名称。
SqlParameter p = new SqlParameter("@uid",txtuid.Text.Trim());
SqlParameter p1 = new SqlParameter("@pwd",txtpwd.Text.Trim());
第三步:
实现Client和Sql服务器之间的交互,即将C#输入框值通过参数p传递给服务器,去执行相应的sql命令(string sql语句)。
SqlCommand cmd = new SqlCommand( sql,conn);
cmd.Parameters.Add(p);
cmd.Parameters.Add(p1);
通过这三步,可以很容易的将拼接字符串的致命缺点:注入攻击进行抵挡。
参数化查询预防注入攻击的实质
参数化实现注入攻击防御实质在于添加转义,给sql语句一转义封装。
当我们在uid登录输入框中输入:
‘ or '1' ='1' --
是 原则上是会判断 or '1'='1' --注释掉后面的密码判断过程。即执行语句:
select * from TestSchool where userId = ' ''+ or '1'='1' -- +'' ' and passWord = ' '' + pwd + '' ' ;
--在sql中表示注释, 原句 -- +'' ' and passWord = ' '' + pwd + '' ' ; 会被忽略,
--变成执行该语句:
select * from TestSchool where userId = ' ''+ or '1'='1'
但是 当我们用参数化查询进行设计时,我们的输入框内容:
' or ‘1’=‘1’-- ; --txtuid.Text.Trim()
' ado or ‘1’=‘1’ ; --txtpwd.Text.Trim()
会经过一次封装过程变成执行这样的语句[在SQL Server Profiler中可查]:
exec sp_executesql
N' select * from TestSchool where userId = @uid and PassWord = @pwd ' ,
N' @uid nvarchar(50), @pwd nvarchar(10)',
@uid = N' '' or '1'='1' -- ',
@pwd = N' '' ado or ‘1’=‘1' '
这里我们明显就看到 整个@uid 变量 被用 N'' 封装了一次,此时的
' or '1'='1' --
的第一个单引号变成了双引号,也就致使他成了一个单纯的字符串值[ ' or '1'='1' -- ]。因此,躲过了sql拼接字符串注入攻击。
第二种参数化查询方式:
用Parameters.AddWithValue();方法
具体如下:
using (SqlCommand cmd=conn.CreateCommand())
{
cmd.CommandText = "select * from TestSchool where userId = @uid and PassWord = @pwd ";
cmd.Parameters.AddWithValue("@uid", ' or ‘1’=‘1’-- );
cmd.Parameters.AddWithValue("@pwd", ' ado or ‘1’=‘1');
}
注意:
1.创建 执行命令实例
SqlCommand cmd=conn.CreateCommand()
2.连接字符串连接方式
cmd.CommandText = "sql 执行语句 ";
3..AddWithValue()方法的使用
cmd.Parameters.AddWithValue("@uid", txtuid.Text.Trim() );
领取专属 10元无门槛券
私享最新 技术干货