PostgreSQL美元引用的字符串常量来防止SQL注入

时间:2011-11-18 21:29:46

标签: postgresql stored-procedures sql-injection sanitization

我可以使用PostgreSQL的Dollar-Quoted字符串常量安全地阻止SQL注入吗?

我知道处理动态查询的最佳方法是在应用程序层中使用参数化查询生成它们,这不是这个问题的内容。所有业务逻辑都在存储过程中。

我有一个存储过程,它接受参数并生成查询,运行它,格式化结果并将其作为一大块文本返回。此函数传递一个表名,列名和WHERE参数。传递给函数的WHERE参数来自用户在数据库中输入的数据。我想确保对stings进行清理,以便构建的查询是安全的。

使用PostgreSQLs Dollar-Quoted Strings Constants,我应该能够安全地清理除'$$'之外的所有字符串输入。但是,如果我在“$”上执行字符串替换以逃避它,我应该能够进行安全的字符串比较。

存储过程:

function_name(tablename text, colnames text[], whereparam text)
--Build dynamic query...

功能调用:

SELECT 
  function_name('tablename', ARRAY['col1', 'col2', 'col3'], 'AND replace(col1, ''$'', ''/$'') =  $$' || replace(alt_string_col, '$', '/$') || '$$ ')
FROM alttable
WHERE alt_id = 123;

生成查询:

SELECT col1, col2, col3 FROM tablename WHERE 1=1 AND replace(col1, '$', '/$') =  $$un/safe'user /$/$ data;$$

由于我在将其与转义用户数据进行比较之前逃离了col1字段,即使用户输入了“un / safe'user $$数据”,在字段alt_string_col中,双美元符号不会破坏查询并且比较通过。

这是一种在PostgreSQL存储过程中转义字符串的安全方法吗?

EDIT1

感谢Erwin Brandstetter。使用USING的{​​{1}}子句,我即将创建一个可以这样调用的函数:

EXECUTE

它为可以传入的WHERE子句提供了一些灵活性。

在存储过程中,我对SELECT function_name( 'tablename', ARRAY['col1', 'col2', 'col3'], ARRAY[' AND col1 = $1 ', ' OR col2 = $5 '], quote_literal(alt_string_col)::text, --Text 1-4 NULL::text, NULL::text, NULL::text, alt_active_col::boolean, --Bool 1-4 NULL::boolean, NULL::boolean, NULL::boolean, NULL::integer, --Int 1-4 NULL::integer, NULL::integer, NULL::integer ) FROM alttable WHERE alt_id = 123; 语句有类似的内容。

EXECUTE

1 个答案:

答案 0 :(得分:4)

在连接标识符时,使用quote_ident()防止SQL注入。或者Postgres 9.1或更高版本中的format()

使用plpgsql代码中的USING clause for EXECUTE传递。或至少quote_literal()

要确保表名存在(并且在连接时自动引用并进行模式限定),请使用special data type regclass

有关使用plpgsql执行动态SQL的更多信息:

从PostgreSQL 9.0开始,您还可以使用anonymous code blocks with the DO statement来执行动态SQL。