SQL注入(未使用预处理语句,直接拼接用户输入到SQL)

VIP/
在Web开发的浩瀚海洋中,安全往往是被新手甚至部分老手忽视的暗礁。其中,SQL注入(SQL Injection) 堪称最古老、最危险,却也是最容易被修复的漏洞之一。今天,我们就来深入剖析这个因“直接拼接用户输入”而引发的灾难,并探讨如何用“预处理语句”构建坚固的防线。

一、什么是SQL注入?

SQL注入是一种代码注入技术,攻击者通过在Web表单输入框或URL参数中插入恶意的SQL代码,欺骗数据库服务器执行非预期的命令。
简单来说,就是用户输入的数据被数据库当成了可执行的代码

核心成因:信任了不该信任的输入

当开发者在编写SQL查询时,如果直接将用户的输入字符串拼接到SQL语句中,而没有进行任何过滤或转义,就打开了潘多拉的魔盒。

二、罪恶的源头:字符串拼接

让我们看一个典型的错误示范。假设我们有一个登录系统,后端代码(以PHP为例)是这样写的:
php

编辑
1// ❌ 极度危险的写法:直接拼接用户输入
2$username = $_POST['username'];
3$password = $_POST['password'];
4
5$sql = "SELECT * FROM users WHERE username = '" . $username . "' AND password = '" . $password . "'";
6
7$result = mysqli_query($conn, $sql);
这段代码看起来逻辑清晰:根据用户名和密码查询用户。但是,如果攻击者在用户名输入框中填入以下内容:
admin' OR '1'='1
那么,最终生成的SQL语句就会变成:
sql

编辑
1SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = '...'
发生了什么?
  • '1'='1' 永远为真(True)。
  • 由于 OR 的存在,整个 WHERE 子句的条件变成了真。
  • 数据库会返回 users 表中的第一条记录(通常是管理员),攻击者无需知道密码即可成功登录!
这仅仅是冰山一角。更严重的注入可以导致:
  • 数据泄露UNION SELECT 窃取整张表的数据。
  • 数据篡改UPDATE 或 INSERT 恶意数据。
  • 删库跑路DROP TABLE users 直接删除表。
  • 服务器沦陷:在某些配置下,甚至可以通过SQL执行系统命令。

三、救赎之道:预处理语句(Prepared Statements)

如何彻底杜绝此类问题?答案只有一个:永远不要拼接SQL字符串,使用预处理语句。

什么是预处理语句?

预处理语句的工作原理是将SQL模板和数据分开处理:
  1. 预编译(Prepare):数据库先解析SQL模板,确定查询结构。此时,占位符(如 ? 或 :name)被视为纯粹的数据位置,而非代码的一部分。
  2. 绑定参数(Bind):将用户输入的数据发送给数据库。数据库会将这些数据严格视为值(Value),即使内容包含SQL关键字,也不会被执行。
  3. 执行(Execute):数据库结合模板和数据进行执行。

正确的代码示范

让我们重写上面的登录逻辑,使用PDO(PHP Data Objects)进行预处理:
php

编辑
1// ✅ 安全的写法:使用预处理语句
2$username = $_POST['username'];
3$password = $_POST['password'];
4
5// 1. 准备SQL模板,使用占位符
6$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
7
8// 2. 绑定参数(PDO会自动处理转义和类型)
9$stmt->execute([
10    ':username' => $username,
11    ':password' => $password
12]);
13
14// 3. 获取结果
15$user = $stmt->fetch();
16
17if ($user) {
18    // 登录成功
19} else {
20    // 登录失败
21}
为什么这样是安全的?
无论用户在 username 中输入 admin' OR '1'='1 还是其他什么妖魔鬼怪,数据库都只会把它当作一个普通的字符串去匹配用户名。它会去寻找一个用户名真的叫 admin' OR '1'='1 的用户,显然这样的用户不存在,查询结果为空,攻击失败。

四、其他语言的实现

预处理思想是通用的,几乎所有现代数据库驱动都支持。

Java (JDBC)

java

编辑
1// ❌ 错误
2String sql = "SELECT * FROM users WHERE id = " + userId;
3
4// ✅ 正确
5String sql = "SELECT * FROM users WHERE id = ?";
6PreparedStatement pstmt = connection.prepareStatement(sql);
7pstmt.setInt(1, userId); // 或者 setString
8ResultSet rs = pstmt.executeQuery();

Python (sqlite3 / pymysql)

python

编辑
1# ❌ 错误
2sql = "SELECT * FROM users WHERE name = '%s'" % user_input
3
4# ✅ 正确
5sql = "SELECT * FROM users WHERE name = ?"
6cursor.execute(sql, (user_input,))

Node.js (mysql2)

javascript

编辑
1// ✅ 正确
2const sql = "SELECT * FROM users WHERE email = ?";
3connection.execute(sql, [email], (err, results) => {
4    // ...
5});

五、结语:安全是一种习惯

SQL注入漏洞存在了二十多年,但直到今天,依然能在许多新上线的系统中发现它的踪影。这往往不是因为技术太难,而是因为开发者的侥幸心理对安全规范的漠视
作为开发者,我们需要铭记以下原则:
  1. 零信任原则:永远不要信任任何来自外部的输入(表单、URL、Cookie、HTTP头)。
  2. 默认使用预处理:将预处理语句作为编写数据库交互代码的唯一标准方式。
  3. 最小权限原则:数据库连接账号不应拥有 DROP 或 FILE 等高危权限,即使被注入,也能将损失降到最低。
代码不仅是逻辑的堆砌,更是责任的承载。一次简单的字符串拼接,可能导致百万用户的数据裸奔;而一个小小的预处理语句,则是守护数字世界安宁的坚实盾牌。

购买须知/免责声明
1.本文部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
2.若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
3.如果本站有侵犯、不妥之处的资源,请在网站右边客服联系我们。将会第一时间解决!
4.本站所有内容均由互联网收集整理、网友上传,仅供大家参考、学习,不存在任何商业目的与商业用途。
5.本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
6.不保证任何源码框架的完整性。
7.侵权联系邮箱:188773464@qq.com
8.若您最终确认购买,则视为您100%认同并接受以上所述全部内容。

海外源码网 源码资讯 SQL注入(未使用预处理语句,直接拼接用户输入到SQL) https://moyy.us/21761.html

相关文章

猜你喜欢