【问题标题】:Substituting column names in Python sqlite3 query [duplicate]在 Python sqlite3 查询中替换列名 [重复]
【发布时间】:2016-02-11 16:54:30
【问题描述】:

我在 sqlite3 数据库中有一个宽表,我希望在 Python 脚本中动态查询某些列。我知道it's bad to inject parameters by string concatenation,所以我尝试使用参数替换。

我发现,当我使用参数替换来提供列名时,会得到意想不到的结果。一个最小的例子:

import sqlite3 as lite

db = lite.connect("mre.sqlite")
c = db.cursor()

# Insert some dummy rows
c.execute("CREATE TABLE trouble (value real)")
c.execute("INSERT INTO trouble (value) VALUES (2)")
c.execute("INSERT INTO trouble (value) VALUES (4)")
db.commit()


for row in c.execute("SELECT AVG(value) FROM trouble"):
    print row   # Returns 3

for row in c.execute("SELECT AVG(:name) FROM trouble", {"name" : "value"}):
    print row   # Returns 0

db.close()

有没有比简单地将列名注入字符串并运行它更好的方法来实现这一点?

【问题讨论】:

标签: python security sqlite


【解决方案1】:

正如 Rob 刚刚在他的评论中指出的那样,有一个相关的 SO 帖子包含我的答案。这些替换结构被称为“占位符”,这就是为什么我最初没有在 SO 上找到答案的原因。列名没有占位符模式,因为dynamically specifying columns is not a code safety issue:

归结为“安全”的含义。传统观点是 使用普通的 python 字符串操作将值放入您的 查询不是“安全的”。这是因为有各种各样的东西 如果你这样做可能会出错,而这些数据通常来自 用户并且不在您的控制范围内。您需要一种 100% 可靠的方式 正确转义这些值,以便用户无法将 SQL 注入 数据值并让数据库执行它。所以图书馆作家做 这份工作;你永远不应该。

但是,如果您正在编写通用帮助代码来操作事物 在数据库中,那么这些考虑因素就不那么适用了。你是 隐含地让任何可以调用此类代码的人访问所有内容 在数据库中;这就是帮助代码的重点。所以现在 安全问题是确保用户生成的数据永远不会 在这样的代码中使用。这是编码中的一般安全问题,并且是 与盲目执行用户输入字符串的问题相同。它是 将值插入查询的明显问题,因为有 您希望能够安全地处理用户输入数据。

因此,解决方案是首先没有问题:使用字符串格式注入值,开心,继续你的生活。

【讨论】:

  • “这不是安全漏洞”并不意味着“没有问题”。给调用者一个不会混淆的错误消息肯定是个问题。就像消除由拼写错误导致的意外正确语法一样。
【解决方案2】:

为什么不使用字符串格式?

for row in c.execute("SELECT AVG({name}) FROM trouble".format(**{"name" : "value"})):
    print row # => (3.0,)

【讨论】:

  • 谢谢!这实际上就是我将列名注入字符串的意思;抱歉,如果不清楚。
猜你喜欢
  • 1970-01-01
  • 2015-05-01
  • 2020-10-13
  • 1970-01-01
  • 2011-06-19
  • 2021-04-19
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
相关资源
最近更新 更多