首页博客网络编程
TL;DR – SQL 注入是一种黑客攻击,它允许入侵者从外部修改数据库。
SQL注入是一种网站攻击,允许黑客扰乱SQL查询。要了解这种攻击会造成什么损害,您需要记住 SQL 用于处理数据库。这意味着入侵者可以访问您保留的数据。
如果幸运的话,他们可能会在您的数据库中插入或更改某些内容。但是,大多数 SQL 注入会导致破坏或窃取敏感信息。对于大型企业来说,其结果尤其具有破坏性——例如,星巴克在 2019 年窃取了大量财务和工资单信息。
在最极端的情况下,黑客甚至可以完全接管数据库的控制权。因此,了解如何防止 SQL 注入至关重要。
为了更好地了解什么是SQL注入,我们将看到一些基本示例。在下面的代码片段中,我们将字符串值分配给一个名为 的变量。我们将通过用户输入获取此变量:txt_user_id
例复制
txt_user_id = getRequestString("user_id"); txt_sql = "SELECT * FROM users WHERE user_id = " + txt_user_id;
假设此代码的最初目标是创建一个 SQL 语句,该语句选择具有特定 ID 的用户。必须有一种方法可以区分有效输入和智能输入,如下所示:
user_id:
例复制
SELECT * FROM users WHERE id = 105 or 1=1
此声明有效。将返回用户的所有行,因为无论如何都是 true。WHERE 1=1
机密信息表(如用户名和密码)很容易成为此类插入的目标。
下面看到的表单通常用于验证用户对网站的登录:
用户名:
密码:
例复制
u_name = getRequestString("user_name"); u_pass = getRequestString("user_pass"); sql = "SELECT * FROM users WHERE username ='" + u_name + "' AND pass ='" + u_pass + "'"
黑客只需在输入表单中输入即可访问不安全的数据库。结果将是有效的,并返回表中的所有行,因为始终为 true:"" or ""=""
users
WHERE ""=""
例复制
SELECT * FROM users WHERE username ="" or ""="" AND password ="" or ""=""
通常,数据库支持联接的 SQL 查询(写在一行中,并用分号分隔)。下面的查询将返回表中的所有行,然后删除名为 :users
customers
例复制
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注入损害,建议将敏感数据分开并存储在多个数据库中。
自定义错误消息,以便它们不会将有关数据库结构的任何信息泄露给潜在的入侵者。
声明提示:若要转载请务必保留原文链接,申明来源,谢谢合作!
广告位
广告位