如何正确保护 GUI 应用程序免受 SQL 注入

How to protect correctly GUI application from SQL injection

提问人:Marilynb 提问时间:2/2/2022 更新时间:2/3/2022 访问量:194

问:

我正在开发一个 GUI 应用程序 (pyQt),用户将在其中添加我想存储在本地数据库 (sqlite) 中的数据。我是这个领域的初学者,即使应用程序没有连接或存储的数据不敏感,我也很想知道如何阻止可能来自用户的“SQL 查询”。 例如,GUI 允许用户添加新物种的名称,我实现了一个控制器,该控制器获取输入的文本,将其传递给 re.sub 以删除任何特殊字符,然后我准备一个查询,传递干净的数据并执行。如果用户输入类似于“SELECT * FROM SPECIES”之类的东西,它就可以工作,用户不能访问数据库中 SPECIES 表中的所有数据存储,但我在我的数据库中得到“SELECTFROMSPECIES”作为新数据,这不是一个好的物种名称。我正在考虑在我的clean_data函数中实现条件,例如“如果条目中的'SELECT':做某事”。另一个问题是,如果用户条目是一个很好的物种名称,但有一些空格作为“Mus musculus”,我的clean_data函数会删除这个空格并存储在数据库“Musmusculus”中。我想知道是否有更干净的方法来避免这些行为并正确解析查询以允许新用户输入,同时保持数据库干净。 提前感谢您的建议。

在这里,我的控制器函数用于清理和存储数据库中的数据:


    def clean_data(self, data):
        clean_data = re.sub('[\W_]+', '', data)
        return clean_data

    def get_data(self, data):
        clean_data = self.clean_data(data)

        self.query.prepare("INSERT INTO SPECIES (specie_name) "
                          "VALUES (:s_name)")
        self.query.bindValue(":s_name", str(clean_data))
        self.query.exec()
SQLite 用户界面 Pyqt SQL注入

评论

0赞 ekhumoro 2/3/2022
无需以任何方式“清理”输入。只要使用占位符,就不会有 sql 注入攻击的危险,因为数据库驱动程序会自动应用正确的引用(基于输入的数据类型)。

答:

1赞 Brian Drake 2/2/2022 #1

我不熟悉PyQt的数据库处理,但是单独调用和调用的全部意义在于它将为您清理值。任何信誉良好的数据库库都会这样做。preparebindValue

事实证明,找到PyQt文档非常困难,但我确实在Real Python上找到了一个页面,上面写着:

在 PyQt 中,结合 、 和 并完全保护您免受 SQL 注入攻击.......prepare().bindValue().addBindValue()

这证实了我上面所说的话。

ekhumoro对这个问题的评论中,链接到占位符的文档

与此相关的是,如果您尝试使用删除非字母字符等技巧来清理数据,则可能会遇到麻烦。要么你会错过一些危险的东西,要么你会因为删除完全安全的文本而惹恼用户。第二个问题可能会导致更复杂的消毒尝试,这将使第一个问题更有可能发生。


以下是更多信息,主要是对评论的回应:

  1. 占位符的作用。使用占位符时,用户的数据仍会直接添加到查询中。但它并没有直接添加到 SQL 语句中:它被适当地引用在前面,以防止 SQL 注入攻击。
  2. 占位符名称。占位符名称是任意的(受 SQL 语法的限制)。它们可能与字段名称相对应,也可能不合适。他们不必这样做,但有时它使它更容易。事实上,在链接的示例中,占位符名称确实与字段名称相对应。
  3. 占位符名称作为键。占位符名称确实可以被视为键,并且在准备查询之前不需要定义(实际上,无法定义)。
  4. 验证。验证是一个与 SQL 注入完全不同的问题。后者可以由图书馆处理,但前者取决于你,因为只有你知道什么是有效的,什么是无效的。 (一旦你清楚地知道什么是有效的,你就可以编写代码来强制执行这一点,如果你需要帮助,请随时问另一个问题。

评论

0赞 Marilynb 2/2/2022
我已经阅读了随附的文档,我仍然有一些问题需要确保我理解正确。占位符是否是一种不直接在已执行的查询中添加用户数据的方法?占位符的名称是任意的,它不应该与我的表字段名称相对应吗?最后,占位符是一种键(像字典一样),我之前不打算定义它吗?这种方法可以防止 sql 注入,但不控制添加的数据,因此由我来在我的clean_data中实现一个代码,允许清理数据并且最终不会得到名称为“SELECTFROMSPECIE”的物种?非常感谢您的帮助
0赞 Brian Drake 2/3/2022
@Marilynb我已经更新了答案。其他几点:(1)“I'ven't”不是一个专有词。即使作为一个以英语为母语的人,我也很难阅读它。(2)在这里,我们更喜欢点赞而不是感谢。你没有足够的声誉来投票,但你可以接受一个答案。
0赞 Marilynb 2/3/2022
好的,现在很清楚了,因为我没有可能投票,我只想说一声非常感谢你的宝贵帮助,当然我验证了答案。(PS 对不起,我的法国校对员做了一个奇怪的完成,我在发送之前没有看到)。再次感谢。