0Pricing
Cyber Security Academy · 课时

SQL 注入防护

防止注入攻击

SQL 注入防护 是 CoddyKit 上的免费 Cyber Security Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Cyber Security Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Cyber Security Academy 课程共包含 4 节课。

什么是 SQL 注入

当不受信任的用户输入被直接拼接到 SQL 查询中时,就会发生SQL 注入(SQLi)。攻击者将 SQL 语法偷偷插入应用程序原本期望接收普通数据的字段,从而改变查询的含义。

SQL 注入至今仍是危害最严重的 Web 漏洞之一,因为它可能泄露整个数据库、绕过登录验证或破坏数据。

存在漏洞的查询

最典型的错误是字符串拼接。当输入为 tom 时,查询没有问题;但经过精心构造的输入会改写查询逻辑。

  • 单引号会提前结束字符串。
  • 后面的所有内容都会变成可执行的 SQL。
query = "SELECT * FROM users WHERE name = '" + userInput + "'";
// userInput = tom' OR '1'='1
// becomes: SELECT * FROM users WHERE name = 'tom' OR '1'='1'

绕过身份验证

登录表单是攻击者的主要目标。通过注入一个恒真的条件并注释掉其余部分,攻击者无需密码即可登录。

-- 序列会注释掉剩余的子句,因此密码检查会被忽略。

-- attacker enters in the username field:
admin' --
-- resulting query:
SELECT * FROM users WHERE user = 'admin' --' AND pass = '...'

参数化查询

主要防御措施是参数化查询(预处理语句)。SQL 结构与数据分开传送,因此输入始终会被视为值,而不是代码。

数据库驱动程序会安全地将 ? 占位符绑定到所提供的值。

-- Python (sqlite3 / psycopg)
cur.execute(
  'SELECT * FROM users WHERE name = ? AND pass = ?',
  (username, password)
)

Java 中的预处理语句

每种主流编程语言都支持参数化。在 Java 中,请使用 PreparedStatement,不要使用 Statement 拼接字符串。

绑定的参数无法脱离自己的位置,因此在这里从结构上杜绝了注入。

PreparedStatement ps = conn.prepareStatement(
  "SELECT * FROM users WHERE name = ?");
ps.setString(1, userInput);
ResultSet rs = ps.executeQuery();

存储过程

如果存储过程在内部使用参数化输入,就能提供帮助。但请注意:如果存储过程通过拼接构建动态 SQL,它同样容易受到攻击。

  • 安全:将参数传递给存储过程。
  • 不安全:在存储过程中对拼接的字符串执行 EXEC()。

输入验证与允许列表

验证是很有用的第二层防御。请使用允许列表(只接受已知的安全模式),而不是拒绝列表(试图禁止不安全字符)。

例如,数字 ID 字段应在输入到达查询之前拒绝任何包含非数字内容的输入。

if not user_id.isdigit():
    raise ValueError('invalid id')
# only then use the value

转义是最后手段

手动转义引号既脆弱又容易出错。不同数据库的转义规则各不相同,边界情况(例如编码技巧和二阶注入)也可能漏网。

请优先使用参数化查询。只有在 ORM 或驱动程序无法对特定标识符进行参数化时,才使用转义。

数据库账户的最小权限

为应用程序数据库用户实施最小权限,以限制成功注入可能造成的损害。

  • 只为所需的表授予 SELECT、INSERT 和 UPDATE 权限。
  • 绝不要在应用程序中使用超级用户或 root 账户。
  • 拒绝 DROP、FILE 以及管理员权限。
GRANT SELECT, INSERT, UPDATE ON appdb.orders TO 'webapp'@'%';
REVOKE DROP, ALTER ON appdb.* FROM 'webapp'@'%';

对象关系映射与查询构建器

现代对象关系映射(ORM)(Hibernate、Sequelize、Django ORM、SQLAlchemy)默认会进行参数化,从而消除了大部分注入风险。

当开发人员改用原始 SQL,或在查询构建器中使用字符串插值时,风险就会重新出现。即使处于原始模式,也始终应将值作为绑定参数传入。

纵深防御

单一控制措施并不足够。请组合使用多层防御:

  • 在所有位置使用参数化查询(主要措施)。
  • 输入验证和允许列表。
  • 采用最小权限的数据库账户。
  • 使用 Web 应用防火墙(WAF)捕获已知模式。
  • 进行错误处理,绝不泄露 SQL 或堆栈跟踪。

快速检查

检验您对主要防御措施的理解。

回顾

您已经了解 SQL 注入的工作原理以及阻止它的方法:

  • SQLi 源于将不受信任的输入拼接到查询中。
  • 参数化查询是主要防御措施。
  • 添加允许列表验证、最小权限的数据库账户和 WAF。
  • 避免手动转义,以及避免在存储过程中使用动态 SQL。

纵深防御可以防止单个错误演变成安全 breach。

常见问题解答

「SQL 注入防护」课时是免费的吗?

是的 — 「SQL 注入防护」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Cyber Security Academy 课程的其余内容,请升级到 CoddyKit PRO。 Cyber Security Academy 课程共包含 4 节课。

「SQL 注入防护」这节课中我会学到什么?

防止注入攻击 你通过在浏览器中直接运行的动手代码来练习 Cyber Security Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Cyber Security Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Cyber Security Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「SQL 注入防护」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Cyber Security Academy 课中编写并运行代码吗?

能。每节 Cyber Security Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. SQL 注入防护
  2. 访问控制与加密
  3. 审计与监控
  4. 备份与恢复安全
← 返回 Cyber Security Academy