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

发布于 2024-12-17 01:38:38 字数 2052 浏览 0 评论 0原文

我可以使用 PostgreSQL 的美元引用字符串常量安全地防止 SQL 注入吗?

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

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

使用 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 $$ data;”在 alt_string_col 字段中,双美元符号不会破坏查询并且比较会通过。

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

编辑1

感谢 Erwin Brandstetter。使用 EXECUTEUSING 子句我打算创建一个可以像这样调用的函数:

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;

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

。存储过程 我有类似这样的 EXECUTE 语句。

  FOR results IN EXECUTE(builtquery) USING 
    textParm1, 
    textParm2, 
    textParm3, 
    textParm4, 
    boolParm1, 
    boolParm2, 
    boolParm3, 
    boolParm4, 
    intParm1, 
    intParm2, 
    intParm3, 
    intParm4
  LOOP
    -- Do some stuff
  END LOOP;

Can I safely prevent SQL Injection using PostgreSQL's Dollar-Quoted String Constants?

I know the best was to handle dynamic queries is to have them generated in a application layer with a parametrized query, that's not what this question is about. All of the business logic is in stored procedures.

I have a stored procedure that takes parameters and generates a query, runs it, formats the results and returns it as a chunk of text. This function is passed a table name, column names and WHERE parameters. The WHERE parameters passed to the function are from user entered data in the database. I would like to make sure that the stings are sanitized so the query that is built is safe.

Using PostgreSQLs Dollar-Quoted Strings Constants, I should be able to safely sanitize all string input other than ' $$ '. However, if I do a string replace on "$" to escape it, I should be able to do a string comparison that is safe.

Stored Procedure:

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

Function Call:

SELECT 
  function_name('tablename', ARRAY['col1', 'col2', 'col3'], 'AND replace(col1, ''

Query Generated:

SELECT col1, col2, col3 FROM tablename WHERE 1=1 AND replace(col1, '

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

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;

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

  FOR results IN EXECUTE(builtquery) USING 
    textParm1, 
    textParm2, 
    textParm3, 
    textParm4, 
    boolParm1, 
    boolParm2, 
    boolParm3, 
    boolParm4, 
    intParm1, 
    intParm2, 
    intParm3, 
    intParm4
  LOOP
    -- Do some stuff
  END LOOP;
', ''/

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


') =  $' || replace(alt_string_col, '

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


, '/

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


) || '$ ')
FROM alttable
WHERE alt_id = 123;

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


, '/

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


', ''/

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


') =  $' || replace(alt_string_col, '

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


, '/

Query Generated:


Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:


It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.


) || '$ ')
FROM alttable
WHERE alt_id = 123;

Query Generated:

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

) = $un/safe'user /$/$ data;$

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

', ''/

Query Generated:

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

') = $' || replace(alt_string_col, '

Query Generated:

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

, '/

Query Generated:

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

) || '$ ') FROM alttable WHERE alt_id = 123;

Query Generated:

Since I'm escaping the col1 field before I compare it to escaped user data, even if the user enters, "un/safe'user $$ data;" in the field, alt_string_col, the double dollar sign does not break the query and the comparison passes.

Is this a safe way to escape strings in PostgreSQL stored procedure?

Edit1

Thanks to Erwin Brandstetter. Using the USING clause for EXECUTE I was about to create a function that can be called like this:

It gives some flexibility to the WHERE clauses that can be passed in.

Inside the stored procedure I have something like this for the EXECUTE statement.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぃ双果 2024-12-24 01:38:38

使用 quote_ident() 来防范连接标识符时的 SQL 注入。或者 format()< /a> 在 Postgres 9.1 或更高版本中。

使用 USING PL/pgSQL 代码中的 EXECUTE 子句用于传递。或者至少是quote_literal()

要确保表名存在(并且在连接时必要时自动引用和模式限定),请使用 特殊数据类型regclass

有关使用 PL/pgSQL 执行动态 SQL 的更多信息:

从 PostgreSQL 9.0 开始,您可以还可以使用 匿名带有DO语句的代码块来执行动态SQL。

Use quote_ident() to safeguard against SQL injection while concatenating identifiers. Or format() in Postgres 9.1 or later.

Use the USING clause for EXECUTE in PL/pgSQL code to pass values. Or at least quote_literal().

To make sure a table name exists (and is quoted and schema-qualified automatically where necessary when concatenated), use the special data type regclass.

More about executing dynamic SQL with PL/pgSQL:

Since PostgreSQL 9.0 you can also use anonymous code blocks with the DO statement to execute dynamic SQL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文