Python中的MySQL,MATCH和注入攻击

1 投票
4 回答
1178 浏览
提问于 2025-04-17 00:51
  1. MySQL中的MATCH也会受到注入攻击的威胁吗?比如:

    """SELECT * 
         FROM myTable 
         WHERE MATCH(myColumnName) AGAINST(%s) 
         ORDER BY id 
         LIMIT 20""" % query
    

    看起来它允许任意字符串,这样就不太安全了。

  2. 如果是这样的话,我尝试了 - 根据Python文档中的例子 -

    t = (query,)
    statement = """SELECT * 
                     FROM myTable 
                     WHERE MATCH(myColumnName) AGAINST(?) 
                     ORDER BY id 
                     LIMIT 20"""
    cursor.execute(statement, t)
    

    但是没有返回任何结果,即使字符串query在上面(1)中有结果。为什么会这样呢?

  3. 在第二种情况下,使用占位符%s而不是?可以返回结果。为什么这比第一种方法更安全呢?比如说,使用查询字符串时,我总是可以用query=')...'来结束一个字符串和括号,然后继续query=') OR otherColumnName LIKE '%hello%' --

所以,仅仅去掉查询字符串中除了罗马字母和数字以外的所有东西,是否就足够安全了呢?

4 个回答

1

第一种方法是不对的,因为它使用了基本的Python字符串格式化,这样做不会对查询字符串进行转义。

第二种方法是发送简单查询到服务器的推荐方式,它会正确地对查询进行转义。

你只是有一个小错误。你需要把 AGAINST(?) 替换成 AGAINST(%s)

相关信息也可以在Python的DbApi常见问题解答中找到。

1

在使用带参数的语句时,MySQLdb会对这些参数进行处理,确保它们是安全的,然后再把这些参数插入到带参数的语句中。最后,它会把完整的字符串语句发送给数据库服务器。你可以信任MySQLdb能够正确处理这些参数,从而防止SQL注入攻击。

MySQLdb/cursors.py:

def execute(self, query, args=None):
    ...
    if args is not None:
        query = query % db.literal(args)

而相比之下,oursql则是把查询和数据完全分开发送到服务器。它不依赖于对数据进行处理,这样应该会更安全。

4

在谈到注入问题时,你用什么操作符、函数、语句或者其他编程语言的术语其实并不重要。注入的关键在于数据和语言语句的混合,也就是说,当你把数据放进语句里时,就可能发生注入。使用准备好的语句参数可以把数据和语句分开,这样就不会受到注入攻击。

至于在参数中使用 ?%s 的区别,MySQLdb 的文档中提到:

    execute(self, query, args=None)

[...]

注意:如果 args 是一个序列,那么在查询中必须使用 %s 作为参数占位符。如果使用的是映射,则必须使用 %(key)s 作为占位符。

撰写回答