如何正确保护 GUI 应用程序免受 SQL 注入
How to protect correctly GUI application from SQL injection
我正在开发一个 GUI 应用程序 (pyQt),用户可以在其中添加我想存储在本地数据库 (sqlite) 中的数据。我是这个领域的初学者,即使应用程序未连接或存储的数据不敏感,我也很想知道如何阻止可能来自用户的“SQL 查询”。
例如,GUI 允许用户添加一个新物种的名称,我实现了一个控制器来获取输入的文本,将其传递给 re.sub 以删除任何特殊字符,然后我准备一个查询,传递干净的数据并执行。如果用户输入类似于“SELECT * FROM SPECIES”,则用户无法访问数据库中 SPECIES table 中的所有数据存储,但我得到“SELECT FROMSPECIES”作为我数据库中的新数据,这不是一个好的物种名称。我正在考虑在我的 clean_data 函数中实现条件,例如“如果 'SELECT' 输入:做某事”。另一个问题是,如果用户输入的是一个好物种的名称,但有一些 space 作为“Mus musculus”,我的 clean_data 函数删除这个 spaces 并存储在数据库“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()
我不熟悉 PyQt 的数据库处理,但是单独调用 prepare
和 bindValue
的全部意义在于它会为您清理值。任何信誉良好的数据库图书馆都会这样做。
事实证明很难找到 PyQt 文档,但我确实在 Real Python 上找到了一个页面,上面写着:
In PyQt, combining .prepare()
, .bindValue()
, and .addBindValue()
fully protects you against SQL injection attacks …
这证实了我上面所说的。
ekhumoro, in a , linked to documentation on placeholders.
在相关说明中,如果您尝试使用删除 non-letter 个字符等技巧来清理数据,您可能会遇到麻烦。要么你会错过一些危险的东西,要么你会通过删除完全安全的文本来惹恼用户。第二个问题可能会导致更复杂的清理尝试,这将使第一个问题更有可能出现。
这里有更多信息,主要是对评论的回应:
- 占位符的作用。使用占位符,用户的数据仍然直接添加到查询。但它没有直接添加到 SQL 语句中:首先适当地引用它,以防止 SQL 注入攻击。
- 占位符名称。 占位符名称是任意的(受 SQL 语法的限制)。它们对应于字段名可能合适也可能不合适。他们不必这样做,但有时这样做会更容易。事实上,在链接示例中,占位符名称 do 对应于字段名称。
- Placeholder names as keys.Placeholder names确实可以认为是keys,不需要定义(确实,不能定义)在准备查询之前。
- 验证。 验证是与 SQL 注入完全不同的问题。后者可以由图书馆来处理,但前者取决于你,因为只有你知道什么是有效的,什么是无效的。 (一旦您清楚地知道什么是有效的,您就可以编写代码来强制执行此操作,如果您需要这方面的帮助,请随时提出其他问题。)
我正在开发一个 GUI 应用程序 (pyQt),用户可以在其中添加我想存储在本地数据库 (sqlite) 中的数据。我是这个领域的初学者,即使应用程序未连接或存储的数据不敏感,我也很想知道如何阻止可能来自用户的“SQL 查询”。 例如,GUI 允许用户添加一个新物种的名称,我实现了一个控制器来获取输入的文本,将其传递给 re.sub 以删除任何特殊字符,然后我准备一个查询,传递干净的数据并执行。如果用户输入类似于“SELECT * FROM SPECIES”,则用户无法访问数据库中 SPECIES table 中的所有数据存储,但我得到“SELECT FROMSPECIES”作为我数据库中的新数据,这不是一个好的物种名称。我正在考虑在我的 clean_data 函数中实现条件,例如“如果 'SELECT' 输入:做某事”。另一个问题是,如果用户输入的是一个好物种的名称,但有一些 space 作为“Mus musculus”,我的 clean_data 函数删除这个 spaces 并存储在数据库“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()
我不熟悉 PyQt 的数据库处理,但是单独调用 prepare
和 bindValue
的全部意义在于它会为您清理值。任何信誉良好的数据库图书馆都会这样做。
事实证明很难找到 PyQt 文档,但我确实在 Real Python 上找到了一个页面,上面写着:
In PyQt, combining
.prepare()
,.bindValue()
, and.addBindValue()
fully protects you against SQL injection attacks …
这证实了我上面所说的。
ekhumoro, in a
在相关说明中,如果您尝试使用删除 non-letter 个字符等技巧来清理数据,您可能会遇到麻烦。要么你会错过一些危险的东西,要么你会通过删除完全安全的文本来惹恼用户。第二个问题可能会导致更复杂的清理尝试,这将使第一个问题更有可能出现。
这里有更多信息,主要是对评论的回应:
- 占位符的作用。使用占位符,用户的数据仍然直接添加到查询。但它没有直接添加到 SQL 语句中:首先适当地引用它,以防止 SQL 注入攻击。
- 占位符名称。 占位符名称是任意的(受 SQL 语法的限制)。它们对应于字段名可能合适也可能不合适。他们不必这样做,但有时这样做会更容易。事实上,在链接示例中,占位符名称 do 对应于字段名称。
- Placeholder names as keys.Placeholder names确实可以认为是keys,不需要定义(确实,不能定义)在准备查询之前。
- 验证。 验证是与 SQL 注入完全不同的问题。后者可以由图书馆来处理,但前者取决于你,因为只有你知道什么是有效的,什么是无效的。 (一旦您清楚地知道什么是有效的,您就可以编写代码来强制执行此操作,如果您需要这方面的帮助,请随时提出其他问题。)