MySQL 及 SQL 注入

SQL 注入原理,以及用预处理(参数化)彻底杜绝。

Beginner
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.

Friends & Partners