- 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 - 选择进入
- SQL - 插入选择
- SQL - 更新查询
- SQL - 删除查询
- SQL - 对结果进行排序
- SQL 视图
- SQL - 创建视图
- SQL - 更新视图
- SQL - 删除视图
- SQL - 重命名视图
- SQL 运算符和子句
- SQL-Where 子句
- SQL - 顶部子句
- SQL - 不同子句
- SQL - Order By 子句
- SQL - Group By 子句
- SQL-Having 子句
- SQL - 与与或
- SQL - 布尔(位)运算符
- SQL - LIKE 运算符
- SQL - IN 运算符
- SQL - ANY、ALL 运算符
- SQL - EXISTS 运算符
- SQL-案例
- SQL - NOT 运算符
- SQL - 不等于
- SQL - 为空
- SQL - 不为空
- SQL - 非空
- SQL - BETWEEN 运算符
- SQL - UNION 运算符
- SQL - UNION 与 UNION ALL
- SQL - 相交运算符
- SQL - EXCEPT 运算符
- 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 - 非聚集索引
- 高级SQL
- SQL - 通配符
- SQL - 注释
- SQL-注入
- SQL-托管
- SQL - 最小值和最大值
- SQL - 空函数
- SQL - 检查约束
- SQL - 默认约束
- SQL-存储过程
- SQL - NULL 值
- SQL - 事务
- SQL - 子查询
- SQL - 处理重复项
- SQL - 使用序列
- SQL-自动递增
- SQL - 日期和时间
- SQL-游标
- SQL - 公用表表达式
- SQL - 分组依据与排序依据
- 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 语句,您将在不知不觉中在数据库上运行该语句。永远不要相信用户提供的数据,仅在验证后处理该数据;通常,这是通过模式匹配完成的。
例子
在下面的示例中,名称限制为字母数字字符加下划线,长度限制在 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 附加一个全新的查询,对数据库的调用变成了灾难;注入的 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}%'");