在Python中使用Psycopg2和以下代码:
import psycopg2
import getpass
conn = psycopg2.connect("dbname=mydb user=%s" % getpass.getuser())
cursor = conn.cursor()
tables = ["user", "group", "partner", "product"]
for table in tables:
# with sql injection
cursor.execute("SELECT name FROM %s LIMIT 1" % (table,))
print "table", table, "result", len(cursor.fetchone())
# without sql injection
cursor.execute("SELECT name FROM %s LIMIT 1", (table,))
print "table", table, "result", len(cursor.fetchone())
结果是:
^{pr2}$有了SQL注入,它工作得很好。在
但我们不想制造安全问题。在
我们阅读了this documentation,其中发现了以下注释:
Only variable values should be bound via this method: it shouldn’t be used to set table or field names. For these elements, ordinary string formatting should be used before running
execute()
.
但如果我们使用“普通字符串格式”,我们也会有SQL注入。在
管理这种特殊情况并避免SQL注入的好方法是什么?在
我认为你混淆了SQL注入的定义。SQL注入是对软件的一种攻击,有人会让你的SQL查询做一些你不想做的事情。字符串插值不是SQL注入。字符串插值有时可以启用SQL注入,但并不总是这样。要了解字符串插值并不总是不安全的,请考虑以下哪项最安全:
sql = 'SELECT name FROM user'
sql = 'SELECT name FROM ' + 'user'
sql = 'SELECT name FROM %s' % ['user']
sql = 'SELECT name FROM {}'.format('user')
这些代码行中的每一行都执行完全相同的操作,因此它们中没有一行比其他行安全。在您的确切示例中,没有SQL注入的危险,因为您只是构建一个硬编码的SQL查询字符串。在
另一方面,如果您的
table
值来自用户,则可能存在安全问题:如果他们传递了一个存在的表的名称,但是你不想让他们查询呢?在
结果:
^{2美元如果他们传递的something实际上不是一个表名怎么办?在
结果:
可以通过检查是否允许表名来防止这种情况:
在
execute
函数中使用psycopg2查询参数是最安全的,并且当参数用作文本时也很容易使用。在(注意
cursor.mogrify()
的行为类似于execute,但只显示格式化的SQL而不实际执行它)但是,当您希望参数是表、模式或其他标识符时,要做到这一点有点困难。您可以使用AsIs包装参数,但这仍然为SQL注入敞开大门。在
^{pr2}$看起来psycopg2的新开发(>;=2.7)将有一个标识符类,您可以在其中包装参数,希望是安全的。如果它还没有发布,或者你还没有,这里有一种方法来创建你自己的类。我将在下面给出一些片段,但您也可以看到my gist。在
如果您已经有一个psycopg2游标实例,可以通过以下方式测试/使用它:
有关自定义类包装SQL参数的机制的更多信息,请参阅文档中的this section。在
我认为您的代码可能只是缺少“;”。你的一行可能看起来像:
如果所有其他方法都失败了,您可以为输入设置一个过滤器,过滤掉控制字符。听起来我很痛苦,但我能做到。那么你的代码看起来像:
^{pr2}$也许你可以使用这个项目:
bleach.readthedocs.io
==================================================
非常好的参考: http://bobby-tables.com/
==================================================
相关问题 更多 >
编程相关推荐