SQL 注入

创建于 2024-12-02 / 30
字体: [默认] [大] [更大]

SQL 注入

SQL 注入是一种可能破坏数据库的代码注入技术

SQL 注入是最常见的 web 黑客技术之一。

SQL 注入是通过网页输入在 SQL 语句中放置恶意代码。


Web 页面中的 SQL

SQL 注入通常发生在您向用户请求输入时,比如 username/userid,用户给您的不是 name/id,而是一条 SQL 语句,您将在不知不觉中在数据库中运行该语句

请看下面的示例,该示例通过向SELECT字符串添加变量(txtUserId)来创建SELECT语句。变量是从用户输入(getRequestString)获取的:

实例

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

本章将介绍在SQL语句中使用用户输入的潜在危险。


基于 1=1 始终为 true 的 SQL 注入

再看看上面的例子。代码的最初目的是创建一个SQL语句来选择具有给定 userid 的用户。

If there is nothing to prevent a user from entering "wrong" input, the user can enter some "smart" input like this:

UserId:

然后,SQL 语句将如下所示:

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

上面的 SQL 是有效的,将返回 "Users" 表中的所有行,因为 OR 1=1 始终为真。

上面的例子看起来危险吗?如果 "Users" 表包含名称和密码怎么办?

上面的 SQL 语句与此基本相同:

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1;

黑客只需在输入字段中插入 105 或 1=1,就可以访问数据库中的所有用户名和密码。



基于 ""="" 始终为 true 的 SQL 注入

以下是用户登录网站的示例:

Username:

Password:

实例

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 ""=" ,即可访问数据库中的用户名和密码:

User Name:

Password:

在服务器上的代码将创建如下有效SQL语句:

Result

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

上面的SQL是有效的,并且将返回"Users"表中的所有行,因为 OR ""="" 始终为 TRUE。


基于批处理SQL语句的SQL注入

大多数数据库支持批处理SQL语句。

批处理SQL语句是由两个或多个SQL语句组成的一组,用分号分隔。

下面的SQL语句将返回"Users"表中的所有行,然后删除"Suppliers"表。

实例

SELECT * FROM Users; DROP TABLE Suppliers

请看以下示例:

实例

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

以及以下输入:

User id:

产生有效的SQL语句如下所示:

Result

SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers;

使用 SQL 参数进行保护

要保护网站不受SQL注入的影响,可以使用 SQL 参数。

SQL 参数是在执行时以受控方式添加到 SQL 查询的值。

ASP.NET Razor 实例

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

请注意,SQ L语句中的参数由 @ 标记表示。

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 中的 SELECT 语句:

txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();

ASP.NET 中的 INSERT INTO 语句:

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 中的 INSERT INTO 语句:

$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();

0 人点赞过