MySQL 及 SQL 注入
SQL 注入原理,以及用预处理(参数化)彻底杜绝。
Key Points把用户输入拼进 SQL 字符串是最大的安全漏洞;参数化查询让输入永远是数据。
危险的拼接
Python
# 错误示范:用户输入直接拼进 SQL
name = request.GET['name']
sql = "SELECT * FROM users WHERE username = '" + name + "'"
# 若 name = "x' OR '1'='1" => 条件永远成立,拖走全表正确的做法:参数化
Python
import pymysql
cur = conn.cursor()
# %s 是占位符,参数由驱动安全转义并作为「数据」传入
cur.execute("SELECT * FROM users WHERE username = %s", (name,))Shell
# 命令行也可用 ? 占位(各语言驱动类似)
mysql> PREPARE stmt FROM 'SELECT * FROM users WHERE username = ?';
mysql> SET @n = 'alice';
mysql> EXECUTE stmt USING @n;Output
+----+----------+-----+
| id | username | age |
+----+----------+-----+
| 1 | alice | 29 |
+----+----------+-----+Never concatenate SQL strings. ORMs parameterize by default; when hand-writing SQL always use placeholders + a parameter tuple, never string formatting.
危险的拼接
Python
# 错误示范:用户输入直接拼进 SQL
name = request.GET['name']
sql = "SELECT * FROM users WHERE username = '" + name + "'"
# 若 name = "x' OR '1'='1" => 条件永远成立,拖走全表正确的做法:参数化
Python
import pymysql
cur = conn.cursor()
# %s 是占位符,参数由驱动安全转义并作为「数据」传入
cur.execute("SELECT * FROM users WHERE username = %s", (name,))Shell
# 命令行也可用 ? 占位(各语言驱动类似)
mysql> PREPARE stmt FROM 'SELECT * FROM users WHERE username = ?';
mysql> SET @n = 'alice';
mysql> EXECUTE stmt USING @n;Output
+----+----------+-----+
| id | username | age |
+----+----------+-----+
| 1 | alice | 29 |
+----+----------+-----+永远不要拼接 SQL 字符串。ORM(SQLAlchemy、GORM、Hibernate)默认参数化;手写 SQL 务必用占位符 + 参数数组,别用字符串格式化把变量塞进去。