首页博客网络编程
如何防止 SQL 注入
摘要 通过过滤输入可以防止最基本的 SQL 注入。但是,它不会阻止更复杂的攻击。 为了防止最大的SQL注入损害,建议将敏感数据分开并存储在多个数据库中。 自定义错误消息,以便它们不会将有关数据库结构的任何信息泄露给潜在的入侵者。

TL;DR – SQL 注入是一种黑客攻击,它允许入侵者从外部修改数据库。

内容

什么是 SQL 注入?

SQL注入是一种网站攻击,允许黑客扰乱SQL查询。要了解这种攻击会造成什么损害,您需要记住 SQL 用于处理数据库。这意味着入侵者可以访问您保留的数据

如果幸运的话,他们可能会在您的数据库中插入或更改某些内容。但是,大多数 SQL 注入会导致破坏窃取敏感信息。对于大型企业来说,其结果尤其具有破坏性——例如,星巴克在 2019 年窃取了大量财务和工资单信息。

在最极端的情况下,黑客甚至可以完全接管数据库的控制权。因此,了解如何防止 SQL 注入至关重要。

基本 SQL 注入示例

为了更好地了解什么是SQL注入,我们将看到一些基本示例。在下面的代码片段中,我们将字符串值分配给一个名为 的变量。我们将通过用户输入获取此变量:txt_user_id

复制

txt_user_id = getRequestString("user_id");
txt_sql = "SELECT *  FROM users WHERE user_id = " + txt_user_id;

1=1

假设此代码的最初目标是创建一个 SQL 语句,该语句选择具有特定 ID 的用户。必须有一种方法可以区分有效输入和智能输入,如下所示:

user_id:

复制

SELECT * FROM users WHERE id = 105 or 1=1

此声明有效。将返回用户的所有行,因为无论如何都是 true。WHERE 1=1

机密信息表(如用户名和密码)很容易成为此类插入的目标。

“”=“” 始终为 True

下面看到的表单通常用于验证用户对网站的登录:

用户名:

密码:

复制

u_name = getRequestString("user_name");
u_pass = getRequestString("user_pass");  

sql = "SELECT * FROM users WHERE username ='" + u_name + "' AND pass ='" + u_pass + "'"

黑客只需在输入表单中输入即可访问不安全的数据库。结果将是有效的,并返回表中的所有行,因为始终为 true:"" or ""=""usersWHERE ""=""

复制

SELECT * FROM users WHERE username ="" or ""="" AND password ="" or ""=""

批处理 SQL 语句

通常,数据库支持联接的 SQL 查询(写在一行中,并用分号分隔)。下面的查询将返回表中的所有行,然后删除名为 :userscustomers

复制

SELECT * FROM users; DROP TABLE customers

想象一下,我们有以下服务器代码和以下输入:

复制

txt_user_id = getRequestString("user_id");
txt_sql = "SELECT *  FROM users WHERE user_id = " + txt_user_id;

用户 ID:

然后,服务器上的代码将创建一个有效的 SQL 语句,如下所示:

SELECT * FROM users WHERE id = 105; DROP TABLE customers


使用参数防止SQL注入

一些 Web 开发实践使用禁用词字典(黑名单)作为 SQL 注入预防措施。在大多数情况下,这种做法很糟糕。黑名单中的大多数词语(例如删除、选择删除)都可以用通用语言使用。

保护网站免受 SQL 注入攻击的唯一行之有效的方法是使用 SQL 保护参数。这些是在执行时添加到 SQL 查询中的自定义值。在 SQL 语句中,SQL 保护参数由标记定义:@

复制

txt_user_id = getRequestString("user_id");
txt_sql = "SELECT *  FROM users WHERE user_id = @0";
db.Execute(txt_sql,txt_user_id);

在处理SQL查询时,会检查每个参数以确保安全。标记始终被视为输入文本,而不是 SQL 查询的一部分:

复制

txt_nam = getRequestString("company_name");
txt_psc = getRequestString("passcode");
txt_add = getRequestString("address");  
txt_sql = "INSERT INTO customers (company_name,passcode,address) Values(@0,@1,@2)";
db.Execute(txt_sql,txt_nam,txt_psc,txt_add);

简单例子

以下示例显示了如何在 ASP.NET 和 PHP 中设置 SQL 注入保护参数。

在第一个示例中,您可以在 ASP.NET 中看到 SELECT 语句的应用:

复制

txt_user_id = getRequestString("user_id");
sql = "SELECT * FROM customers WHERE customer_id = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txt_user_id); 
command.ExecuteReader();

下面是在 ASP.NET 中使用 INSERT INTO 语句的示例:

复制

txt_nam = getRequestString("company_name");
txt_psc = getRequestString("passcode");
txt_add = getRequestString("address"); 
txt_sql = "INSERT INTO customers (company_name,passcode,address) Values(@0,@1,@2)";
command = new SqlCommand(txt_sql); 
command.Parameters.AddWithValue("@0",txt_nam);
command.Parameters.AddWithValue("@1",txt_psc); 
command.Parameters.AddWithValue("@2",txt_add);
command.ExecuteNonQuery();

在最后一个示例中,我们将在 PHP 中使用 INSERT INTO 语句:

复制

$stmt = $dbh->prepare("INSERT INTO Customers (CompanyName,Passcode,Address) VALUES (:nam, :psc, :add)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':psc', $txtPsc);
$stmt->bindParam(':add', $txtAdd);
$stmt->execute();

如何防止SQL注入:有用的提示

  • 通过过滤输入可以防止最基本的 SQL 注入。但是,它不会阻止更复杂的攻击。

  • 为了防止最大的SQL注入损害,建议将敏感数据分开并存储在多个数据库中

  • 自定义错误消息,以便它们不会将有关数据库结构的任何信息泄露给潜在的入侵者。



声明提示:若要转载请务必保留原文链接,申明来源,谢谢合作!

本文链接:https://www.gaoxuejun173.top/blog/232

广告位

本文配乐
来说两句吧

该文章已禁止评论

最新评论

广告位