sql注入

错误根源

每次在将动态内容与sql语句拼接时都要考虑sql注入的风险。问题根源在于没有将数据与代码(sql语句)进行分离,这个和xss很类似。示例:

sql = 'SELECT * FROM bugs WHERE bug_id = ' + '1; DELETE * FROM users;'
session.execute(sql)

防御方法

1. 过滤输入

过滤用户输入的不合法字符
如整数类型转换

bug_id = int(bug_id)
sql = 'SELECT * FROM bugs WHERE bug_id = %d;' % bug_id

如动态按列排序,假如表中字段名称只包含字母,数字和下划线

import re
order_by = re.sub(r'[^\w_]', '', order_by)
sql = 'SELECT * FROM bugs ORDER BY %s;' % order_by
# 用户即使输入 order_by = 'user; DELETE * FROM xxx;' 也会被转换为order_by = 'userDELETEFROMxxx'
# 执行错误但没有安全问题

2. 参数化动态内容

强有力的防御手段,对于动态数据十分有效。使用查询参数将数据与SQL表达式分离。参数化查询,数据库先将带?的SQL表达式编译好之后,才套用参数执行。如sqlite:

cursor.execute('INSERT INTO people VALUES (?, ?)', (who, age))

3. 数据与代码隔离

对于表名,字段名,sql关键字需要动态化的,可以使用隔离方式。建立用户输入与sql动态部分的映射关系,如字典。让用户界面与查询细节解耦,同时不将用户输入与sql语句拼接,降低风险。如:

  field_map = {
    'age': 'people_age',
    'gender': 'people_gender'
    ...
  }
  # order_by = 'age' 
  order_by = field_map.get(order_by, 'default')
  sql = 'SELECT * FROM people ORDER BY %s;' % order_by
    原文作者:简写_
    原文地址: https://www.jianshu.com/p/fb9091dd2c05
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞