【问题标题】:psycopg2 and SQL injection securitypsycopg2 和 SQL 注入安全性
【发布时间】:2017-12-21 02:03:28
【问题描述】:

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

目前,项目规范仅指示硬编码情况。即“函数#1需要列出点集A到点集B在500m内的所有距离。函数#2需要列出点集C到点集D的所有距离......”等等。

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

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

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

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

【问题讨论】:

    标签: python postgresql postgis psycopg2


    【解决方案1】:

    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:

    警告永远,永远,永远不要使用 Python 字符串连接 (+) 或字符串参数插值 (%) 将变量传递给 SQL 查询字符串。甚至在枪口下也没有。

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

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

    Asis()... 用于其字符串表示已经作为 SQL 表示有效的对象。

    所以,不要在用户输入中使用它。

    【讨论】:

    • 所以主要的收获是:不要使用AsIs()。设置表名之类的东西有什么限制吗?我似乎记得在某处读过你可以通过execute() 命令输入值,但你不应该在表名中使用它。这听起来对还是我完全关闭?是的,我从不使用字符串连接,也从不使用字符串参数/格式。但我有点困惑,因为我开始认为即使使用 execute() 命令也是不安全的,这开始让我想知道图书馆的全部意义是什么
    • 那么AsIs(input)input 之间有什么区别?使用AsIs()会绕过卫生吗?
    • 是的,我认为AsIs() 绕过了卫生设施。不要将它与用户的输入一起使用。我个人只将它用于单元测试。 stackoverflow.com/questions/13793399/…
    • @1saac 我刚刚编辑了我的答案以指出这一点:initd.org/psycopg/docs/extensions.html#psycopg2.extensions.AsIs
    • 好的,谢谢。所以在 SQL 查询中使用用户输入并不是不安全的,只要你没有使用AsIs(),并且你使用的是cur.execute() 命令,并且没有使用字符串连接/参数/格式
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-14
        • 1970-01-01
        • 2021-02-28
        • 1970-01-01
        • 2010-10-12
        相关资源
        最近更新 更多