如何使用Java在PostgreSQL中安全地转义SQL的任意字符串

2022-09-02 13:06:06

我有一个特殊情况,要求我从用户提供的输入值生成SQL WHERE子句的一部分。我想防止任何类型的SQL注入漏洞。我想出了以下代码:

private String encodeSafeSqlStrForPostgresSQL(String str) {

  //Replace all apostrophes with double apostrophes
  String safeStr = str.replace("'", "''");

  //Replace all backslashes with double backslashes
  safeStr = safeStr.replace("\\", "\\\\");

  //Replace all non-alphanumeric and punctuation characters (per ASCII only)
  safeStr = safeStr.replaceAll("[^\\p{Alnum}\\p{Punct}]", "");

  //Use PostgreSQL's special escape string modifier
  safeStr = "E'" + safeStr + "'";

  return safeStr;
}

问题:

  • 您看到任何问题了吗?
  • 您能提供更好的解决方案吗?
  • 是否有任何现有的库可以帮助解决这个问题?

笔记:

  • 这是SO和其他地方的常见问题,但我看到的唯一答案是始终使用ReadyStatements。Fwiw,我正在使用JasperReports。我想将查询保留在JasperReports中。用于查询参数处理的内置 Jasper 参数函数(包括 X{} 函数)不足以满足我需要参数化的内容。我可以尝试创建一个自定义的 Jasper QueryExecutor,它允许我注入自己的 X{} 函数,但这比仅仅生成一个带有 Jasper $P的动态 SQL where 子句要复杂得多!{} 语法。

  • 我查看了OWASP库。他们还没有PostgresSQL编解码器。我看了一下OracleCodec,它的逃逸似乎过于简单。我不确定它对防止SQL注入攻击有多大帮助。

  • 在我的代码中,我添加了E,以便不依赖于PostgreSQL的standard_conforming_strings设置。理想情况下,我不必添加它,然后该函数就不必是PostgreSQL特定的。更多信息: http://www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE .

理想情况下,我想要一个更通用和健壮的解决方案,我知道这将是安全的,并支持所有可能的UTF-8字符串。


答案 1

最简单的方法是使用PostgreSQL的Dollar Quoteing与一个小的随机标签相结合:

  • 对于每个调用,计算一个小的随机标记(例如4个字符)(冗余)
  • 查看引号标记是否是输入字符串的一部分。
  • 如果是,请重新计算新的随机标记。
  • 否则,请像这样构建查询:

    $tag$inputString$tag$
    

通过这种方式,您可以摆脱不同嵌套引用技术的全部麻烦,还可以使用随机标签设置移动目标。

根据您的安全要求,这可能会完成或没有完成这项工作。


答案 2

我在这里问了一个类似的问题,但我认为最好的办法是使用。这是一个Postgres库,所以使用它应该是安全的。如果/当Postgres添加新的字符串分隔符时,应更新此方法。org.postgresql.core.Utils.escapeLiteral


推荐