ado.net访问数据库流程2-防注入攻击

什么是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() );

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181128A1TM4500?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券