我们有一个构建一些XML的函数,并使用EXECUTE / USING来防止SQL注入。这是:
CREATE OR REPLACE FUNCTION public.f1(t TEXT)
RETURNS XML AS
$BODY$
DECLARE
ret_val XML;
BEGIN
EXECUTE 'SELECT ''<'' || $1 || ''>'''
--rest of xml building
INTO ret_val
USING t;
RETURN ret_val;
END
$BODY$
LANGUAGE plpgsql IMMUTABLE;
由于连接,我不喜欢这么多。如果我们可以做SELECT '''<$1>''
会更好,但结果是文字$ 1而不是用值替换它。
由于连接,它让我想知道我们是否甚至需要SQL注入预防。它不是从表中读取,只是构建一个返回的XML字符串。
在这种情况下,不使用USING
是否存在实际风险?连接$ 1会否定USING
的影响,或者USING
是否会对不使用表的语句产生任何影响?
答案 0 :(得分:1)
此处没有SQL注入的危险,因为您使用的是USING
。
请注意,您可能一直在使用静态SQL来实现相同的目标:
SELECT '<' || t || '>' INTO ret_val;
答案 1 :(得分:1)
这里要解开一些东西。
首先,你在那里的SQL实际上是一个固定的字符串:
'SELECT ''<'' || $1 || ''>'''
所以没有什么可以直接注入这里,因为没有动态SQL。正如Laurenz Albe指出的那样,这个特定示例中的SQL可以写成非动态语句:
SELECT '<' || t || '>'
此处仍然没有SQL注入,因为您不是评估 t
的内容,只是将其作为字符串进行操作,就像SELECT a + 1
一样将a
操纵为数字。
关键是实际的SQL是硬编码的,而连接只是该SQL中的指令。
请注意,这个看似相似的查询会是危险的(语法突出显示了差异的线索):
EXECUTE 'SELECT ''<' || t || '>''' -- DON'T DO THIS!
这里,t
的值被用作作为SQL字符串的一部分 - 首先发生连接,然后执行结果。因此,'1'; DROP TABLE users; --'
的值会导致查询SELECT '<1'; DROP TABLE users; --
,这显然是不受欢迎的。
其次,作为explained in the docs,$1
是参数,由USING
子句作为数据提供,因此它SQL注入也是安全的。这类似于在数据库外部的编程语言中使用参数化查询 - 您将查询构建为字符串,仔细地将引用的表和列列入白名单,然后单独提供变量数据,而不能将其重新解释为SQL。或者换句话说,它就像另一个函数&#34;更深一层......&#34;,USING子句指定的参数就像实际函数的参数一样。
最后,请注意: 或危险的XML。例如,考虑如果t
的值为t
并且结果最终解析为HTML,会发生什么。