Python中的MySQL,MATCH和注入攻击
MySQL中的
MATCH
也会受到注入攻击的威胁吗?比如:"""SELECT * FROM myTable WHERE MATCH(myColumnName) AGAINST(%s) ORDER BY id LIMIT 20""" % query
看起来它允许任意字符串,这样就不太安全了。
如果是这样的话,我尝试了 - 根据Python文档中的例子 -
t = (query,) statement = """SELECT * FROM myTable WHERE MATCH(myColumnName) AGAINST(?) ORDER BY id LIMIT 20""" cursor.execute(statement, t)
但是没有返回任何结果,即使字符串
query
在上面(1)中有结果。为什么会这样呢?在第二种情况下,使用占位符
%s
而不是?
可以返回结果。为什么这比第一种方法更安全呢?比如说,使用查询字符串时,我总是可以用query=')...'
来结束一个字符串和括号,然后继续query=') OR otherColumnName LIKE '%hello%' --
。
所以,仅仅去掉查询字符串中除了罗马字母和数字以外的所有东西,是否就足够安全了呢?
4 个回答
第一种方法是不对的,因为它使用了基本的Python字符串格式化,这样做不会对查询字符串进行转义。
第二种方法是发送简单查询到服务器的推荐方式,它会正确地对查询进行转义。
你只是有一个小错误。你需要把 AGAINST(?)
替换成 AGAINST(%s)
。
相关信息也可以在Python的DbApi常见问题解答中找到。
在使用带参数的语句时,MySQLdb会对这些参数进行处理,确保它们是安全的,然后再把这些参数插入到带参数的语句中。最后,它会把完整的字符串语句发送给数据库服务器。你可以信任MySQLdb能够正确处理这些参数,从而防止SQL注入攻击。
MySQLdb/cursors.py:
def execute(self, query, args=None):
...
if args is not None:
query = query % db.literal(args)
而相比之下,oursql则是把查询和数据完全分开发送到服务器。它不依赖于对数据进行处理,这样应该会更安全。
在谈到注入问题时,你用什么操作符、函数、语句或者其他编程语言的术语其实并不重要。注入的关键在于数据和语言语句的混合,也就是说,当你把数据放进语句里时,就可能发生注入。使用准备好的语句参数可以把数据和语句分开,这样就不会受到注入攻击。
至于在参数中使用 ?
和 %s
的区别,MySQLdb 的文档中提到:
execute(self, query, args=None)[...]
注意:如果 args 是一个序列,那么在查询中必须使用 %s 作为参数占位符。如果使用的是映射,则必须使用 %(key)s 作为占位符。