psycopg2 和 SQL 注入安全

psycopg2 and SQL injection security

我正在编写 class 以用作更大的建模算法的一部分。我的部分进行空间分析以计算从某些点到其他点的距离。有多种条件,包括返回距离的数量、截止距离等。

目前,项目规范仅指示硬编码情况。即 "Function #1 needs to list all the distances from point set A to point set B within 500m. Function #2 needs to list all the distances from point set C to point set D..." 等等。

我不想硬编码这些参数,开发下一阶段模型的人也不想,因为显然他们想调整参数或可能在其他项目中重新使用算法他们会有不同的条件。

现在的问题是我正在使用 psycopg2 来执行此操作。这是我工作的标准,所以我没有选择偏离它的选择。我已经读到,由于 SQL 注入的明显原因,公开将作为参数放入执行的查询中的参数是一个非常糟糕的主意。但是,我认为 psycopg2 会自动清理 SQL 输入。我认为问题在于使用 AsIs 函数。

简单的解决方案就是按照项目中的规定对其进行硬编码,但这对我来说感觉很懒惰和草率。我不喜欢偷懒和草率的工作。

允许用户输入将输入到 psycopg2 执行的查询中的参数完全安全吗?或者只是使用 AsIs 不安全?如果我想让用户能够输入这些参数,我是否必须自己负责对输入进行消毒,如果是这样,是否有一种快速简便的方法来做到这一点,就像另一个 python 图书馆什么的?

AsIs 是不安全的,除非你真的知道自己在做什么。例如,您可以将它用于单元测试。

传递参数并不是那么不安全,只要您不预先格式化您的 sql 查询。从不这样做:

sql_query = 'SELECT * FROM {}'.format(user_input)
cur.execute(sql_query)

因为 user_input 例如可以是 ';DROP DATABASE;'

相反,执行:

sql_query = 'SELECT * FROM %s'
cur.execute(sql_query, (user_input,))

pyscopg2 将清理您的查询。此外,如果您真的不信任用户的输入,您可以使用自己的逻辑预先清理代码中的参数。

根据 psycopg2's documentation:

Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.

此外,我永远不会让我的用户告诉我应该查询哪个 table。您的应用程序的逻辑(或路由)应该告诉您这一点。

关于 AsIs(),根据 psycopg2's documentation

Asis()... for objects whose string representation is already valid as SQL representation.

所以,不要将它与用户输入一起使用。

您可以使用 psycopg2.sql 来编写动态查询。与 AsIs 不同,它将保护您免受 SQL 注射。

如果您需要将查询存储在变量中,您可以使用 SQL 方法 (documentation):

from psycopg2 import sql


query = sql.SQL("SELECT * FROM Client where id={clientId}").format(clientId=sql.Literal(clientId)