1. 核心定义
SQL 注入:攻击者将恶意 SQL 命令插入用户输入(表单、查询字符串等),因输入未验证 / 转义,欺骗服务器执行恶意 SQL 查询,非法操作数据库。
MySQL 注入:针对 MySQL 数据库的 SQL 注入,核心是利用输入漏洞构造恶意 SQL,执行非预期查询或破坏数据。
2. 典型攻击示例
(1)登录验证注入
原查询语句:SELECT * FROM users WHERE username = 'input_username' AND password = 'input_password';
攻击者输入用户名:' OR '1'='1'; --
篡改后语句:SELECT * FROM users WHERE username = '' OR '1'='1'; --' AND password = 'input_password';
结果:1=1 恒成立,注释符--屏蔽后续语句,返回所有用户数据。
(2)未过滤的删除注入
name = "Qadir'; DELETE FROM users;"
cursor.execute(f"SELECT * FROM users WHERE name='{name}'") # 动态拼接SQL存在注入风险
风险:未过滤name变量,可能导致 users 表数据被删除(SQLite/PostgreSQL 中该风险更高)。
3. 防范措施
| 措施类型 | 具体内容 |
|---|---|
| 基础防护 | 1. 参数化查询 / 预编译语句(分离输入与查询语句,从根源规避注入)2. 输入验证 + 转义(正则校验格式 / 限制长度,使用驱动自带转义函数处理特殊字符)3. 数据库最小权限(为应用分配独立账号,仅赋予必要操作权限) |
| 辅助防护 | 1. 使用 ORM 框架(如 SQLAlchemy、Django ORM,抽象 SQL 查询降低风险)2. 生产环境禁用详细错误提示(避免泄露数据库结构等敏感信息) |
4. 特殊场景:like 语句注入
-
问题:用户输入
_(匹配单个字符)、%(匹配任意字符)会导致查询结果异常; -
解决(Python):先通过数据库驱动转义特殊字符,再手动处理
%和_,示例(基于 pymysql):import pymysql conn = pymysql.connect(host='localhost', user='root', password='', db='test') cursor = conn.cursor() # 转义基础特殊字符 + 处理like专用通配符 user_input = "%something_" escaped_input = conn.escape_string(user_input) # 基础转义 like_safe_input = escaped_input.replace('%', '\\%').replace('_', '\\_') # 处理%/_ cursor.execute(f"SELECT * FROM table WHERE col LIKE '{like_safe_input}'")
5. Python 核心防注入函数 / 方法
| 方法 / 函数名 | 所属库 / 场景 | 作用 |
|---|---|---|
| conn.escape_string() | pymysql(MySQL 驱动) | 转义用户输入中的 MySQL 特殊字符(单引号、双引号、反斜杠等) |
| re.match()/re.fullmatch() | re(正则库) | 正则验证输入格式(如限制用户名仅含字母 / 数字 / 下划线,长度 8-20 位) |
| cursor.execute (参数化 SQL, 参数元组) | 所有 Python 数据库驱动 | 参数化查询核心用法,彻底分离 SQL 结构与输入,示例:cursor.execute("SELECT * FROM users WHERE username=%s AND password=%s", (input_user, input_pwd)) |
| sqlalchemy.text() | SQLAlchemy(ORM) | 构造安全的带参数 SQL 语句,避免拼接风险,示例:from sqlalchemy import text``stmt = text("SELECT * FROM users WHERE username=:name")``result = conn.execute(stmt, {"name": input_user}) |
6. 防注入 6 个核心要点
- 永远不信任用户输入,必须校验(正则、长度限制、转义特殊字符);
- 不使用字符串拼接生成 SQL,优先用参数化查询(cursor.execute 带参数元组);
- 避免使用管理员权限的数据库连接,为每个应用分配独立低权限账号;
- 敏感信息(如密码)通过 hash 加密存储(Python 推荐使用 bcrypt、passlib 库);
- 用自定义错误信息包装原始异常,减少信息泄露;
- 用专业工具(sqlmap、Acunetix)检测注入漏洞,定期审计代码。