SQL 教程

SQL 教程 SQL 简介 SQL 语法 SQL Select SQL Select Distinct SQL Where SQL And, Or, Not SQL Order By SQL Insert Into SQL Null Values SQL Update SQL Delete SQL Select Top SQL Min 和 Max SQL Count, Avg, Sum SQL Like SQL 通配符 SQL In SQL Between SQL 别名 SQL 联接 SQL Inner Join SQL Left Join SQL Right Join SQL Full Join SQL 自联接 SQL Union SQL Group By SQL Having SQL Exists SQL Any, All SQL Select Into SQL Insert Into Select SQL Case SQL Null 函数 SQL 存储过程 SQL 注释 SQL 运算符

SQL 数据库

SQL 创建数据库 SQL 删除数据库 SQL 数据库备份 SQL Create Table SQL Drop Table SQL Alter Table SQL 约束 SQL Not Null SQL Unique SQL Primary Key SQL Foreign Key SQL Check SQL Default SQL Index SQL 自动增量 SQL 日期 SQL 视图 SQL 注入 SQL 托管 SQL 数据类型

SQL 参考手册

SQL 关键字 MySQL 函数 SQL Server 函数 MS Access 函数 SQL 快速参考手册

SQL 实例

SQL 实例 SQL 测验 SQL 练习


SQL 注入

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