SQL 注入是一种可能会破坏数据库的代码注入技术。
SQL 注入是最常见的网络黑客技术之一。
SQL注入是通过网页输入在SQL语句中放置恶意代码。
SQL 注入通常发生在您要求用户输入信息(例如用户名/用户 ID)时,用户会向您提供一条 SQL 语句,而不是名称/ID。不知不觉地在您的数据库上运行。
看下面的例子,它创建了一个 SELECT
通过将变量 (txtUserId) 添加到选择字符串来声明。该变量是从用户输入中获取的(getRequestString):
txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
本章的其余部分描述在 SQL 语句中使用用户输入的潜在危险。
再看一下上面的例子。该代码的最初目的是创建一个 SQL 语句来选择具有给定用户 ID 的用户。
如果没有什么可以阻止用户输入 "wrong" 输入,则用户可以输入一些 "smart" 输入,如下所示:
用户身份:
然后,SQL 语句将如下所示:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
上面的 SQL 是有效的,并将返回 "Users" 表中的所有行,因为或 1=1始终为真。
上面的例子看起来很危险吗?如果 "Users" 表包含名称和密码怎么办?
上面的 SQL 语句与下面的 SQL 语句非常相似:
SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1;
黑客只需在输入字段中插入 105 OR 1=1 就可以访问数据库中的所有用户名和密码。
以下是用户登录网站的示例:
用户名:
密码:
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass + '"'
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
黑客只需将 " OR ""=" 插入用户名或密码文本框中即可访问数据库中的用户名和密码:
用户名:
密码:
服务器上的代码将创建一个有效的 SQL 语句,如下所示:
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
上面的 SQL 是有效的,并将返回 "Users" 表中的所有行,因为或 ""=""始终为真。
大多数数据库都支持批量SQL语句。
一批 SQL 语句是一组两个或多个 SQL 语句,以分号分隔。
下面的 SQL 语句将返回 "Users" 表中的所有行,然后删除 "Suppliers" 表。
SELECT * FROM Users; DROP TABLE Suppliers
看下面的例子:
txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
以及以下输入:
用户身份:
有效的 SQL 语句如下所示:
SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers;
要保护网站免受 SQL 注入,您可以使用 SQL 参数。
SQL 参数是在执行时以受控方式添加到 SQL 查询的值。
txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
请注意,参数在 SQL 语句中由 @ 标记表示。
SQL 引擎检查每个参数,以确保其对于其列来说是正确的,并且按字面意思处理,而不是作为要执行的 SQL 的一部分。
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
以下示例展示了如何使用一些常见的 Web 语言构建参数化查询。
ASP.NET 中的选择语句:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
在 ASP.NET 中插入语句:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
在 PHP 中插入语句:
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();
截取页面反馈部分,让我们更快修复内容!也可以直接跳过填写反馈内容!