This question already has answers here:
How to prepare SQL query dynamically (column names too) avoiding SQL injection
                                
                                    (2个答案)
                                
                        
                        
                            MySQL parameterized queries
                                
                                    (7个答案)
                                
                        
                                9个月前关闭。
            
                    
我尝试在pymysql中使用UPDATE语句来更新某些列的值,其中self.keyself.valueself.id是三个变量。

cur.execute("UPDATE environment_history SET {key}=%s WHERE id=%s".format(key=self.key),
                    (self.value, self.id)
                    )


在上面的代码中,这为SQL注入留下了机会。我们只需要发布一些这样的数据

{"id":"23151","key":"uuid='ac211';#","value":"abcde"}


这将更新所有行,这可能更危险。
我必须阻止这种情况的发生。

我尝试了一些不切实际的解决方案,其中之一是:

cur.execute("UPDATE environment_history SET %s=%s WHERE id=%s",
                    (self.key,self.value, self.id)
                    )


但是,pymysql会将列名转义为\'uuid\'之类。

这是一个SQL语法错误,因为SET col_name=3和SET`col_name` = 3是正确的。

那么,如何避免这种SQL注入呢?

尝试手动替换和转义self.key是我能想到的唯一选择,但这听起来不像是一种优雅的方法。

我的数据库是MySQL。

有任何想法吗?谢谢!

最佳答案

根据我对类似动态查询的经验,建议您将表/键定义保存在某处,并检查它们是否有效。

基本思想是保留表的有效键的字典,例如:

valid_keys = {
   'table1': ['key1', 'key2', 'key3'],
   'table2': ['key1', 'key2'],
   ...
}


并进行简单检查,例如:

keys = valid_keys[table] if table in valid_keys.keys() else None
if keys != None and key in keys:
   # do your query stuff


您可以将该检查放入方法/函数中,并使之更加简单,而无需重复自己的操作:

# checks table and key validity
def query_data_valid(table, key):
   keys = valid_keys[table] if table in valid_keys.keys() else None
   if keys != None and key in keys:
      return True

   return False

...
# block in your query calling method
if query_data_valid(table, key):
   # do your query stuff

关于python - 当列是动态的时,如何避免在UPDATE语句SET%s =%s中进行SQL注入(inject),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56003207/

10-09 18:50