- SQL 教程
- SQL 首页
- SQL 概述
- SQL - RDBMS 概念
- SQL - 数据库
- SQL - 语法
- SQL - 数据类型
- SQL - 运算符
- SQL - 表达式
- SQL 数据库
- SQL - 创建数据库
- SQL - 删除数据库
- SQL - 选择数据库
- SQL - 重命名数据库
- SQL - 显示数据库
- SQL - 数据库备份
- SQL 表
- SQL - 创建表
- SQL - 显示表
- SQL - 重命名表
- SQL - 截断表
- SQL - 克隆表
- SQL - 临时表
- SQL - 修改表
- SQL - 删除表
- SQL - 删除表
- SQL - 约束
- SQL 查询
- SQL - 插入查询
- SQL - 选择查询
- SQL - SELECT INTO
- SQL - INSERT INTO SELECT
- SQL - 更新查询
- SQL - 删除查询
- SQL - 排序结果
- SQL 视图
- SQL - 创建视图
- SQL - 更新视图
- SQL - 删除视图
- SQL - 重命名视图
- SQL 运算符和子句
- SQL - WHERE 子句
- SQL - TOP 子句
- SQL - DISTINCT 子句
- SQL - ORDER BY 子句
- SQL - GROUP BY 子句
- SQL - HAVING 子句
- SQL - AND & OR
- SQL - 布尔 (BIT) 运算符
- SQL - LIKE 运算符
- SQL - IN 运算符
- SQL - ANY, ALL 运算符
- SQL - EXISTS 运算符
- SQL - CASE
- SQL - NOT 运算符
- SQL - 不等于
- SQL - IS NULL
- SQL - IS NOT NULL
- SQL - NOT NULL
- SQL - BETWEEN 运算符
- SQL - UNION 运算符
- SQL - UNION 与 UNION ALL
- SQL - INTERSECT 运算符
- SQL - EXCEPT 运算符
- SQL - 别名
- SQL 连接
- SQL - 使用连接
- SQL - 内连接
- SQL - 左连接
- SQL - 右连接
- SQL - 交叉连接
- SQL - 全连接
- SQL - 自连接
- SQL - 删除连接
- SQL - 更新连接
- SQL - 左连接与右连接
- SQL - UNION 与 JOIN
- SQL 键
- SQL - 唯一键
- SQL - 主键
- SQL - 外键
- SQL - 组合键
- SQL - 备选键
- SQL 索引
- SQL - 索引
- SQL - 创建索引
- SQL - 删除索引
- SQL - 显示索引
- SQL - 唯一索引
- SQL - 聚簇索引
- SQL - 非聚簇索引
- 高级 SQL
- SQL - 通配符
- SQL - 注释
- SQL 注入
- SQL - 托管
- SQL - MIN & MAX
- SQL - NULL 函数
- SQL - CHECK 约束
- SQL - DEFAULT 约束
- SQL - 存储过程
- SQL - NULL 值
- SQL - 事务
- SQL - 子查询
- SQL - 处理重复项
- SQL - 使用序列
- SQL - 自动递增
- SQL - 日期和时间
- SQL - 游标
- SQL - 公共表表达式
- SQL - GROUP BY 与 ORDER BY
- SQL - IN 与 EXISTS
- SQL - 数据库调优
- SQL 函数参考
- SQL - 日期函数
- SQL - 字符串函数
- SQL - 聚合函数
- SQL - 数值函数
- SQL - 文本和图像函数
- SQL - 统计函数
- SQL - 逻辑函数
- SQL - 游标函数
- SQL - JSON 函数
- SQL - 转换函数
- SQL - 数据类型函数
- SQL 有用资源
- SQL - 问答
- SQL - 快速指南
- SQL - 有用函数
- SQL - 有用资源
- SQL - 讨论
SQL 注入
如果您通过网页获取用户输入并将其插入 SQL 数据库,则您可能存在一个名为SQL 注入的安全漏洞风险。本章将教您如何预防此问题,并帮助您保护服务器端脚本(例如 PERL 脚本)中的脚本和 SQL 语句的安全。
SQL 注入
SQL 注入是一种安全攻击,它利用数据库中的漏洞来执行恶意查询。这将允许攻击者访问敏感数据,篡改数据以及永久删除数据。
注入通常发生在您向用户索取输入(例如他们的姓名)时,他们提供的不是姓名,而是一个您会在不知情的情况下在数据库上运行的 SQL 语句。永远不要信任用户提供的数据,只有在验证后才能处理此数据;通常,这是通过模式匹配完成的。
示例
在下面的示例中,name 限制为字母数字字符加上下划线,长度在 8 到 20 个字符之间(您可以根据需要修改这些规则)。
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) { $result = mysqli_query("SELECT * FROM CUSTOMERS WHERE name = $matches[0]"); } else { echo "user name not accepted"; }
为了演示这个问题,请考虑以下摘录:
// supposed input $name = "Qadir'; DELETE FROM CUSTOMERS;"; mysqli_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");
此函数调用应该从 CUSTOMERS 表中检索一条记录,其中 name 列与用户指定的 name 匹配。在正常情况下,$name 只包含字母数字字符和空格。但是在这里,通过将一个全新的查询附加到 $name,对数据库的调用变成了灾难;注入的 DELETE 查询删除了 CUSTOMERS 表中的所有记录。
幸运的是,如果您使用的是 MySQL,mysqli_query() 函数不允许查询堆叠或在一个函数调用中执行多个 SQL 查询。如果您尝试堆叠查询,则调用会失败。
但是,其他 PHP 数据库扩展(例如SQLite 和PostgreSQL)会愉快地执行堆叠查询,执行一个字符串中提供的所有查询,并造成严重的安全问题。
防止 SQL 注入
您可以在 PERL 和 PHP 等脚本语言中巧妙地处理所有转义字符。PHP 的 MySQL 扩展提供了函数mysql_real_escape_string() 来转义对 MySQL 特殊的输入字符。
if (get_magic_quotes_gpc()) { $name = stripslashes($name); } $name = mysql_real_escape_string($name); mysqli_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");
LIKE 难题
为了解决 LIKE 难题,自定义转义机制必须将用户提供的 '%' 和 '_' 字符转换为字面量。使用addcslashes(),这是一个允许您指定要转义的字符范围的函数。
$sub = addcslashes(mysql_real_escape_string("%str"), "%_"); // $sub == \%str\_ mysqli_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");