FlawOpen

flawopen.com/SQL Injection/ORM 够吗?

使用 ORM 足以防止 SQL 注入吗?

参考页面
简短回答

ORM 像一间根据订单表做菜的厨房:常规查询构造器会分开传递数据值。原生 SQL 快捷接口是另一条通道,也有自己的规则。先核实具体 API,再判断插值值是否安全。

不安全 — 用户文本拼入 FromSqlRaw SQL
var sql = $"SELECT * FROM dbo.Blogs WHERE Url = '{url}'";
var rows = await context.Blogs
    .FromSqlRaw(sql)
    .ToListAsync();
// User text is inserted into SQL before execution.
安全 — 使用 FromSql 绑定插值(EF Core 7+)
var rows = await context.Blogs
    .FromSql($"SELECT * FROM dbo.Blogs WHERE Url = {url}")
    .ToListAsync();
// EF Core 7+: interpolation becomes a SQL parameter.

这些 API 如何处理值

ORM 查询构造器和原生 SQL API 并非统一的安全边界。官方文档说明了安全绑定值的方法:Django raw(sql, params)、使用独立执行参数的 SQLAlchemy text()、Rails 占位符条件、EF Core 7+ FromSql / FromSqlInterpolated、GORM Raw(sql, args...),以及 Prisma 标签模板 $queryRaw。原生 API 的行为不同:FromSqlRaw 单独接收参数时可安全使用,但把用户文本插入 SQL 字符串则不安全;$queryRawUnsafe 也能单独绑定值,但拼接不可信文本仍然不安全。方法名称本身无法说明值的处理方式。请按 API 文档绑定每个数据值。SQL 标识符和查询结构不能作为参数,应从应用控制的固定允许列表中选择。下方指南说明各 API 的具体约定。

"足够"实际需要什么

FAQ

原生 SQL 方法一定不安全吗?

不一定。有些原生 SQL API 会绑定单独传入的值,有些安全 API 会把插值值作为参数。EF Core 7+ 的 FromSql 接受插值 FormattableString;FromSqlRaw 需要单独传参。Prisma 的 $queryRawUnsafe 也能绑定值,但不会清理自行拼接的 SQL 文本。请核实具体方法约定,确保不可信值不进入 SQL 结构。

参考资料

另请参阅 SQL 注入(CWE-89):原理与各编程语言的防护方法 — flawopen.com Knex.js 能防止 SQL 注入吗? MyBatis ${} 与 #{}:防止 SQL Injection MySQLi 与 PDO:安全使用预处理语句 NHibernate 能防止 SQL 注入吗? MongoDB NoSQL 注入:安全查询过滤器 数字 ID 使用字符串拼接也会导致 SQL 注入吗?