~/VibeHandbook
$39

18 · 02

注入:当输入变成了代码

注入是最古老、至今仍最常见的严重漏洞。它发生在用户提供的数据被当成指令而不是数据来处理的时候。对大多数应用来说,有两种类型值得关注。

SQL injection(SQL 注入)是用户输入混进了数据库查询。经典的脆弱写法:

// VULNERABLE: 用户的输入被直接粘进了查询里
app.get("/user", (req, res) => {
  const name = req.query.name;
  db.query(`SELECT * FROM users WHERE name = '${name}'`);
});
// 如果有人传入  name = '; DROP TABLE users; --
// 你的查询就变成了一条删表的命令。

修复办法是用参数化查询(也叫预编译语句)。你把查询和数据分开发送,这样数据库就永远不会把其中一个错当成另一个:

// SAFE: 值作为参数传入,永远不作为代码
app.get("/user", (req, res) => {
  const name = req.query.name;
  db.query("SELECT * FROM users WHERE name = ?", [name]);
});

规则是:永远不要用字符串拼接来构造查询。 如果你在 diff 里看到反引号或 + 把 SQL 拼在某个变量周围,停下来,要求改成参数化的版本。

XSS(cross-site scripting,跨站脚本) 是同一个思路在浏览器里的版本。如果你拿用户输入、把它当作原始 HTML 塞进页面,攻击者就能注入一个 <script> 标签,让它在你其他用户的浏览器里运行——比如窃取他们的会话。修复办法是转义:把用户内容当作文本来渲染,而不是 HTML。像 React 这样的现代框架默认会转义,这很棒——直到 AI 为了“让它能跑”伸手去用 dangerouslySetInnerHTMLinnerHTML 这种逃生口。这些会绕过保护。在 diff 里看到任何这类调用,都要当成需要质疑的东西。

每个注入漏洞背后统一的原则是:让数据和代码保持分离。 每当用户输入要进入一个查询、一条命令、一个模板或 HTML 时,总得有东西去转义它或参数化它。

想离线阅读?

获取 PDF + EPUB + 可下载的提示词库 + 版本更新。

$ 获取 PDF — $39