背景
sqlite3模块(here)的python文档说:
通常,您的SQL操作需要使用Python中的值 变量。 您不应该使用Python的字符串汇编查询 操作因为这样做是不安全的;它使你的程序 容易受到SQL注入攻击(请参阅http://xkcd.com/327/) 什么可能出错的幽默例子。)
相反,您应该让sqlite3库为您替换,使用占位符的问号,依赖于该库的DB-API参数替换机制的实现。
文档后面跟着一个例子:
# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
问题
使用DB-API的参数替换代替使用python字符串操作自己构建查询:
a)以某种方式固有的更安全(请解释)
或
b)“仅仅”是一个非常棒的主意,因为它使用了一个经过良好测试的现有库,可以为我进行清理,从而节省了无数小时的调试和无数的漏洞和攻击?
对该问题的评论和想法
我怀疑b(尤其是因为像this one这样的答案)。如果答案是a,那么我不明白这里存在一个微妙的不安全因素,这种不安全感需要在某处解释。
令人困惑的一点是,对于给出的例子,绝对没有任何不安全感。它非常明显地(100%的时间)减少到:
c.execute("SELECT * FROM stocks WHERE symbol = 'RHAT'")
这是非常好的。
这是一种糟糕的编程风格,因为后来的用户可能很容易将符号更改为来自外部源,这样会不安全,如下所示:
symbol = raw_input("enter a stock symbol")
#symbol comes straight from the user! what horrors it could contain...
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
甚至可以认为这是不安全的:
def get_stock(symbol):
#goodness knows where symbol comes from or whether it has been
#sanitized properly yet...
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
我正在寻找确认原始示例不是不安全,而是糟糕的编程习惯,因为它可能很容易变得不安全。这是两件不同的事情,了解它们之间的区别非常重要。
答案 0 :(得分:2)
python docs中引用的示例确实显然是无害的,因为您可以完全控制symbol
变量。所以它与下面的静态查询完全相同,如你所说:
"SELECT * FROM stocks WHERE symbol = 'RHAT'"
但即使它是无害的,如果没有明确的评论说明你为什么这样做以及为什么它是安全的,你就不应该这样做。至少有两个原因:
答案 1 :(得分:0)
我只能说xkcd说:)
symbol = raw_input("enter a stock symbol")
带输入
'; DELETE FROM stocks; SELECT * FROM stocks WHERE symbol='
使用
连接"SELECT * FROM stocks WHERE symbol = '%s'" % symbol
将创建具有意外结果的有效SQL查询;)
答案 2 :(得分:0)
这个例子确实是安全的。
但是,这不是真正的程序所能做的,而只是为了表明symbol
具有某些值。
在实践中,价值将来自计划之外,这是不安全的。 即使程序使用这样的常量值,以后的添加和扩展也可能会添加动态符号选择,任何想要进行更改的人都会忘记查看SQL。