这段Python代码是否容易受到SQL注入攻击?(针对SQLite3)

23

正如标题所示,我想知道这段代码是否容易受到SQL注入攻击?如果是,有更好、更安全的方法实现同样的功能吗?

def add(table,*args):
    statement="INSERT INTO %s VALUES %s" % (table,args)
    cursor.execute(statement)
1个回答

41

是的,可以使用类似这样的方法来防止它发生:

cursor.execute("INSERT INTO table VALUES ?", args)

请注意,您不能像这样输入表格。理想情况下,表格应该是硬编码的,在任何情况下都不应该来自用户的任何输入。您可以使用类似于表格的字符串,但最好确保用户无法以某种方式更改它...有关更多详细信息,请参见我可以在sqlite3中使用表名参数吗?
基本上,您希望将参数放入光标命令中,因为它会确保使数据数据库安全。通过您的第一个命令,相对容易制作出一个特殊的 table args ,将某些东西放入您的SQL代码中,这并不安全。请参见python pages和引用的http://xkcd.com/327/。具体来说,Python页面引用如下:
通常,您的SQL操作需要使用Python变量中的值。不应使用Python的字符串操作来组装查询,因为这样做是不安全的;它会使您的程序容易受到SQL注入攻击的威胁(有关可能出现的问题的幽默示例,请参见http://xkcd.com/327/)。相反,使用DB-API的参数替换。在您想要使用值的任何位置放置?作为占位符,然后将一个值元组作为第二个参数提供给游标的execute()方法。(其他数据库模块可能使用不同的占位符,例如%s或:1。)
基本上,某人可以设置一个args以执行另一个命令,就像这样:
args="name; DELETE table"

使用cursor.execute将填入给定的值,因此参数可以按列出的方式进行,并且当您对其进行查询时,您将获得确切的结果。XKCD也以幽默的方式解释了这一点。

enter image description here


1
谢谢。您能详细解释一下为什么它是易受攻击的吗? - Sheldon
2
可能很明显,但为了安全起见:对于所有语句都要这样做,而不仅仅是INSERT。SELECT语句同样容易受到攻击。 - Niclas Nilsson
2
5个赞,已被接受,却没有人检查吗?(https://dev59.com/YG025IYBdhLWcg3wqn4N) - lqc
3
为什么/如何使用参数(?)和使用(%s)不会在提供相同的输入(table,args)字符串时返回相同的可执行SQL代码,您能否详细解释一下? - RyanKDalton
5
使用参数意味着sqlite3(或其他数据库库)可以按照其想要的方式绑定参数。它可能只是确保一切都被正确引用和转义(可能使用特定于数据库管理系统的功能,或者以其他难以正确实现的方式)。或者,在解析SQL语句为内部格式之后,它可能实际上会绑定参数(这很可能更快,也更安全)。重点是,任何数据库接口都需要对参数进行某种安全处理,而对于字符串,您必须自己找出并执行相同的操作(并且会做错)。 - abarnert
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接