参数化查询为什么可以避免sql注入
发布网友
发布时间:2022-04-07 17:58
我来回答
共3个回答
懂视网
时间:2022-04-07 22:19
参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,这个方法目前已被视为最有效可预防SQL注入攻击 (SQL
Injection) 的攻击手法的防御方式。
原理
在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有恶意的指令,由于已经编译完成,就不会被数据库所运行。
有部份的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部份功能上会非常不便,然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失。
SQL 指令撰写方法
在撰写 SQL 指令时,利用参数来代表需要填入的数值,例如:
Microsoft
SQL Server
Microsoft SQL Server 的参数格式是以 "@" 字符加上参数名称而成,SQL Server 亦支持匿名参数 "?"。
SELECT * FROM myTable WHERE myID = @myID
INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)
ADO.NET
SqlCommand sqlcmd = new SqlCommand("INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)", sqlconn);
sqlcmd.Connection = conn; //连接字符串
sqlcmd.CommandText = sql; //sql语句
sqlcmd.Parameters.Add("@c1",SqlDbType.Text,30).Value=c1; //赋值
//或:
sqlcmd.Parameters.AddWithValue("@c1", 1); // 设定参数 @c1 的值。
sqlcmd.Parameters.AddWithValue("@c2", 2); // 设定参数 @c2 的值。
sqlcmd.Parameters.AddWithValue("@c3", 3); // 设定参数 @c3 的值。
sqlcmd.Parameters.AddWithValue("@c4", 4); // 设定参数 @c4 的值。
sqlconn.Open();
sqlcmd.ExecuteNonQuery();
sqlconn.Close();
SQL参数化查询
标签:sql server microsoft 参数化查询
热心网友
时间:2022-04-07 19:27
因为参数化查询时,参数与SQL语句是分开提供的,攻击者构造的参数不会被拼接入SQL字符串,也就无法实现SQL注入攻击了
热心网友
时间:2022-04-07 20:45
首先创建一张表Users:
CREATE TABLE [dbo].[Users](
[Id] [uniqueidentifier] NOT NULL,
[UserId] [int] NOT NULL,
[UserName] [varchar](50) NULL,
[Password] [varchar](50) NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
3F3ECD42B7A24B139ECA0A7D584CA195
插入一些数据:
INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),1,'name1','pwd1');
INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),2,'name2','pwd2');
INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),3,'name3','pwd3');
INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),4,'name4','pwd4');
INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),5,'name5','pwd5');
假设我们有个用户登录的页面,代码如下:
验证用户登录的sql 如下:
select COUNT(*) from Users where Password = 'a' and UserName = 'b'
这段代码返回Password 和UserName都匹配的用户数量,如果大于1的话,那么就代表用户存在。
本文不讨论SQL 中的密码策略,也不讨论代码规范,主要是讲为什么能够防止SQL注入,请一些同学不要纠结与某些代码,或者和SQL注入无关的主题。
可以看到执行结果:
15C19A6170754E21A52A79AAA01B9B48
这个是SQL profile 跟踪的SQL 语句。
5CB6FB63846740C494C6466FE27D2B3C
注入的代码如下:
select COUNT(*) from Users where Password = 'a' and UserName = 'b' or 1=1—'
这里有人将UserName设置为了 “b' or 1=1 –”.
实际执行的SQL就变成了如下:
782A96FEE0784A39B5500CAE267B90EE
5A8FCD361FFE414AB18AEE5C9ED681DE
可以很明显的看到SQL注入成功了。