在这篇文章中,我们将研究如何保护自己和应用程序数据免受来自外部来源的恶意攻击。 我们正在研究的第一个条目是参数化查询,以帮助防止SQL Injection攻击。 我经常看到很多人,尤其是新程序员,他们使用的代码与格式化后的数据库进行交互:
public bool LoginToSystem(string un, string pwd)
{
int count = 0;
using (var conn = new SqlConnection("YourConnectionStringHere"))
{
string sql = "SELECT COUNT(userId) FROM users WHERE userName = '" + un + "' AND password = '" + pwd + "'";
using (var cmd = new SqlCommand(sql, conn))
{
conn.Open();
count = (int)cmd.ExecuteScalar();
}
}
return count > 0 ? true : false;
}
现在有些人会看这个例子,首先想到“那是什么问题?”。
好吧,这就是所谓的SQL注入,并且使用上面所示的代码非常适合这种攻击。
- SQL注入是一种攻击,其中将恶意代码插入字符串中,然后将这些字符串传递给SQL Server实例以进行解析和执行。
给定以上示例,我们可以为用户名和密码值提供值[il]'或'1'='1 [/ il],并且我们将能够正常登录,因为这样做会导致执行在您的数据库中:
- 从用户名中选择COUNT(userId),其中userName =” OR'1'='1'AND password =“ OR'1'='1'
由于1始终等于1,因此有人可以访问您的系统,相信我,这不是您想要发生的事情。 如果上述sql语句保持原状,可能会产生轻微的结果,因此这将产生以下脚本以在数据库中执行。 通过这种格式化语句的方式,某人可以添加; DROP TABLE用户-正如您可以想象的那样,这将带来灾难性的后果。 如果执行该操作,那么数据库将显示以下内容:
- 从用户那里选择COUNT(userId)userName =” AND password =”; DROP TABLE用户–
分号告诉数据库一个执行将要结束,而另一个执行将要开始,语句末尾的–告诉SQL语句的其余部分是注释,因此请忽略它。 这会做什么,那么它将删除您的users表。
因此,您可以对此采取什么措施,可以采取的最大保护措施之一就是使用参数化查询。 使用参数化的语句将您的值嵌入到该语句中,这使得某人将命令注入代码中变得更加困难。
因此,让我们看一下如何使用参数化查询来保护自己,从而纠正上述情况。 请记住,此示例适用于MSSQL,但我还将展示如何针对Microsoft Access进行此操作。 为此,我们将使用
SqlParameterCollection类的 AddWithValue方法,用于创建参数化查询。新代码(用于MSSQL)如下所示:
public bool LoginToSystemParameterized(string un, string pwd)
{
int count = 0;
using (var conn = new SqlConnection("YourConnectionStringHere"))
{
string sql = "SELECT COUNT(userId) FROM users WHERE userName = @username AND password = @password";
using (var cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.CommandType = System.Data.CommandType.Text;
//now add our parameters
cmd.Parameters.AddWithValue("@username", un);
cmd.Parameters.AddWithValue("@password", pwd);
count = (int)cmd.ExecuteScalar();
}
}
return count > 0 ? true : false;
}
对于Microsoft Access,我们将不得不对语句做一些小的修改,使其看起来像这样
public bool LoginToSystemParameterized(string un, string pwd)
{
int count = 0;
using (var conn = new SqlConnection("YourConnectionStringHere"))
{
string sql = "SELECT COUNT(userId) FROM users WHERE userName = ? AND password = ?";
using (var cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.CommandType = System.Data.CommandType.Text;
//now add our parameters
cmd.Parameters.AddWithValue("@username", un);
cmd.Parameters.AddWithValue("@password", pwd);
count = (int)cmd.ExecuteScalar();
}
}
}
return count > 0 ? true : false;
}
在MSSQL中,@ parametername是占位符,表示我们要嵌入到语句中的值,在Access中,您使用问号吗?
占位符。
当此新查询发送到SQL Server时,由系统存储过程执行
- sp_executesql。 因此对于SQL Server,此查询如下所示
exec sp_executesql N'SELECT COUNT(userId)from users where userName = @username AND password = @ password,'N @ username varchar(15),'N'@ password varchar(25)',@ username ='yourname',@密码='yourp密码'
因此,如您所见,使用参数化查询可以大大保护您自己,您的应用程序和数据以及您的雇主/用户免受来自外部来源的恶意攻击
From: https://bytes.com/topic/net/insights/941310-role-parametrized-queries