在Postgres中,准备好的查询和用户定义的函数是否等同于防止SQL注入的机制?
一种方法相对于另一种方法是否具有特殊优势?

#1 楼

这取决于。
SQL函数
对于LANGUAGE sql来说,答案通常是肯定的。
只要您不调用不安全的函数,就将传递的参数视为值,并且无法进行SQL注入从正文和传递参数开始。
PL / pgSQL函数
对于LANGUAGE plpgsql来说,答案通常是肯定的。
但是,PL / pgSQL允许在动态SQL中将传递的参数(或部分)串联在一起到查询字符串并使用EXECUTE执行。这样可以将用户输入转换为SQL代码,并使SQL注入成为可能。您无法从外部判断功能主体是否正确处理了它。提供了工具。
仅在需要时使用动态SQL。使用参数作为值的普通SQL语句可以像SQL函数一样防止SQL注入。
对于动态SQL,最好将值作为值传递给以下内容:

USING子句。示例。

使主体上无法进行SQL注入。
如果在SQL字符串中连接值,请使用:


format()和格式说明符%L。例如。

quote_literal()quote_nullable()。示例。

安全地将字符串括在单引号中,从而避免了语法错误和SQL注入。
使用以下参数将处理参数视为SQL字符串中的标识符:


format(),带有格式说明符%I。示例。

quote_ident()。例如。
表名称:regclass的注册类型转换为_tbl::regclass。示例。

在需要的地方安全地将标识符字符串用双引号引起来,从而避免语法错误和SQL注入。
相关:

将PL / pgSQL函数重构为返回各种SELECT查询的输出
将表和列名定义为plpgsql函数中的参数?

永远不要仅仅根据用户输入来构建字符串并执行。这包括由用户直接传递或从系统目录中获取的标识符。构建动态SQL时,所有内容都应视为用户输入并适当引用!
此相关答案中有关性能含义的更多信息:

函数性能

SQL的基础-injection:

http://bobby-tables.com/

类似的注意事项也适用于其他允许动态SQL的服务器端语言。

评论


因此,总而言之:如果1)我仅使用语言sql,则很安全; 2)如果我使用plpgslq但未执行,我很安全; 3)如果我使用plpgsql并执行但没有标识符和%s或% L是适当的,我很安全,或者4)如果我使用plpgsql并执行和标识符,但%I或quote_ident则我是安全的。正确?

– MickeyfAgain_BeforeExitOfSO
2013年9月12日在17:28

@mickeyf:基本上是。另外,尽可能使用USING子句将值传递给EXECUTE。您可以从SQL函数中调用PL / pgSQL函数并传递参数。因此,绝对正确,只要您不直接或间接调用任何不安全的函数,便可以安全。如果所有功能都正确完成,那将不会发生。

–欧文·布兰德斯特(Erwin Brandstetter)
2013年9月12日21:13在