![]()
八股文学习网站:https://interviewguide.cn
SQL 注入(SQL Injection)是一种常见的网络攻击手段,攻击者通过在 Web 应用程序的输入字段中插入恶意 SQL 代码,欺骗后台数据库执行非授权的 SQL 语句。
SQL 注入可以用于获取、篡改或删除数据库中的数据,甚至可以用于执行系统命令,导致数据泄露、数据破坏或服务器被控制等严重后果。
1、SQL 注入的工作原理
对用户输入验证不足:当 Web 应用程序没有正确验证用户输入时,攻击者可以在输入字段中插入 SQL 代码。
拼接 SQL 语句:应用程序后端通常将用户输入与 SQL 查询拼接在一起,形成完整的数据库查询语句。
执行恶意 SQL:如果应用程序没有对输入进行适当的转义,恶意 SQL 代码将被数据库服务器执行。
数据泄露或破坏:攻击者可以利用 SQL 注入来查询、修改或删除数据库中的数据,或者执行数据库管理系统的系统命令。
当用户登录网站时,通常会输入用户名和密码。
以下是一段正常的 SQL 查询代码:
SELECT * FROMusersWHERE username = 'user1'ANDpassword = 'password1';
如果攻击者输入:
用户名:admin' --
密码:anything
SQL 查询变成:
SELECT * FROMusersWHERE username = 'admin'--' AND password = 'anything';
其中 -- 是 SQL 的注释符号,忽略了密码条件,直接绕过了身份验证。
比如以下代码,就会出现被注入的情况:
const express = require('express');const mysql = require('mysql');const app = express();app.use(express.json());const connection = mysql.createConnection({host: 'localhost',user: 'root',password: 'password',database: 'testdb'});app.post('/login', (req, res) => {const { username, password } = req.body;// 不安全的 SQL 查询const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;connection.query(query, (error, results) => {if (error) {return res.status(500).send('Database error');}if (results.length > 0) {res.send('Login successful');} else {res.send('Invalid username or password');}});});app.listen(3000, () => {console.log('Server running on http://localhost:3000');});
2、常见 SQL 注入
2.1、基础型 SQL 注入
直接将恶意 SQL 代码嵌入用户输入中,并影响查询逻辑。
输入用户名:admin' OR '1'='1
输入密码:anything
执行的 SQL 查询:
SELECT * FROMusersWHERE username = 'admin'OR'1'='1'ANDpassword = 'anything';
结果:
OR '1'='1' 总为 true,可以绕过验证。
2.2、UNION 查询注入
通过 UNION 将攻击者构造的查询结果与合法查询结果合并,从而获取敏感数据。
输入:
' UNION SELECTnull, username, passwordFROMusers--
执行的 SQL 查询:
SELECTid, nameFROM products WHEREid = ''UNIONSELECTnull, username, passwordFROMusers--';
结果:
将 users 表的 username 和 password 数据作为结果返回。
2.3、错误型 SQL 注入
通过故意触发数据库错误,利用错误信息推测表名、列名或数据。
输入:
' AND 1=CONVERT(int, (SELECT @)) --
执行的 SQL 查询:
SELECT * FROMusersWHERE username = ''AND1=CONVERT(int, (SELECT @@version)) --';
结果:
错误信息可能暴露数据库版本或其他信息。
2.4、盲注
无法直接获取查询结果,攻击者通过判断返回页面的响应(如布尔值或时间延迟)来逐步推测数据。
布尔型盲注,输入:
' AND (SELECT1WHERESUBSTRING((SELECTdatabase()), 1, 1)='t') --
执行的 SQL 查询:
SELECT * FROMusersWHERE username = ''AND (SELECT1WHERESUBSTRING((SELECTdatabase()), 1, 1)='t') --';
结果:
根据返回结果判断数据库名首字母是否为 t。
时间盲注,输入:
' AND IF(1=1, SLEEP(5), 0) --
执行的 SQL 查询:
SELECT * FROMusersWHERE username = ''ANDIF(1=1, SLEEP(5), 0) --';
结果:
如果条件成立,服务器会延迟 5 秒响应,从而泄露信息。
2.5、堆叠查询注入
允许多条 SQL 语句同时执行。
输入:
'; DROPTABLEusers; --
执行的 SQL 查询:
SELECT * FROMusersWHERE username = ''; DROPTABLEusers; --';
结果:
users 表被删除。
当然,也可以执行修改管理员密码的SQL命令:
SELECT * FROMusersWHERE username = ''; UPDATEuserssetpassword='123456'whereuser='admin'; --';
某些数据库(如 MySQL)默认不支持多语句执行。
2.6、存储过程注入
利用存储过程的输入参数注入恶意 SQL。
输入:
'; EXEC xp_cmdshell('dir'); --
执行的 SQL:
EXEC LoginProcedure 'username', ''; EXEC xp_cmdshell('dir'); --'
结果:
执行系统命令(如列出目录)。
2.7、Cookie 注入
利用修改浏览器存储的 Cookie 值进行注入。
Cookie: session_id=' OR '1'='1;
服务器在解析 Cookie 时执行了恶意 SQL。
3、防范措施
3.1、参数化查询和预编译语句
使用参数化查询或预编译语句,将用户输入与 SQL 语句分离,避免用户输入被直接解析为 SQL 代码。
Java 代码:
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";PreparedStatement pstmt = connection.prepareStatement(sql);pstmt.setString(1, username);pstmt.setString(2, password);ResultSet rs = pstmt.executeQuery();
Node.js (MySQL 模块):
const query = "SELECT * FROM users WHERE username = ? AND password = ?";connection.query(query, [username, password], (err, results) => {if (err) throw err;// Handle results});
3.2、使用 ORM 框架
核心思路 ORM(如 Hibernate、Sequelize 等)通过自动生成 SQL 查询,大幅减少手动拼接 SQL 的机会,从而避免注入。
// 使用 Sequelizeconst user = await User.findOne({where: { username: 'admin', password: 'password123' }});
3.3、输入验证
严格检查用户输入是否符合预期,拒绝不符合规则的输入。
对用户名、邮箱等使用正则表达式,数值类型字段只允许数字输入。
对特殊字符进行转义(如 " 转为 \")。
const username = req.body.username.replace(/[^a-zA-Z0-9]/g, ''); // 清理特殊字符
3.4、限制数据库权限
为数据库用户分配最小权限,只允许执行必要的操作。
限制写入权限:只允许插入、更新的用户操作对应的表,不允许 DROP、ALTER 等高危操作。
分离读写权限:使用只读账号访问数据库。
创建一个只读用户:
CREATEUSER'readonly_user'@'%'IDENTIFIEDBY'secure_password';GRANTSELECTON database_name.* TO'readonly_user'@'%';
3.5、定期安全测试
通过安全扫描工具或手动测试,定期检查代码中的潜在 SQL 注入漏洞。
我们可以使用开源工具 SQLMap 来测试。
SQLMap 是一个专门用于自动化进行 SQL 注入检测和利用的渗透测试工具。
SQLMap 广泛应用于网络安全评估和渗透测试中,帮助发现和修复SQL注入漏洞。
SQL 官方地址:https://sqlmap.org/
SQLMap 开源地址:https://github.com/sqlmapproject/sqlmap
好文推荐
你好,我是阿秀,普通学校毕业,校招时拿到字节跳动SP、百度、华为、农业银行等6个互联网中大厂offer,这是我在校期间的编程学习之路,点击蓝字即可查看我是如何自学技术以应对第二年的校招的全过程。
毕业后我先于抖音部门担任全栈开发工程师,目前在上海某外企带领团队继续从事全栈开发,负责的项目已经顺利盈利300w+。在研三那年就组建了一个阿秀的学习圈,持续分享校招/社招跳槽找工作的经验,目前已经累计服务22、23、24、25、26届同学,共计超过 4400 +人,欢迎点此🔗加入我们,一群人才能走的更远、更稳、更顺。

