面试题答案
一键面试整体实现思路
- 获取输入:从Web应用的请求中获取可能存在SQL注入风险的参数值,例如用户输入的表单数据、URL参数等。
- 检测逻辑:
- 对获取到的参数值进行分析,利用正则表达式和SQL语法知识来判断是否存在潜在的SQL注入风险。
- 针对不同数据库类型,需要有相应的适配规则,因为不同数据库的SQL语法存在一定差异。
- 结果输出:将检测结果反馈给用户,告知是否存在SQL注入风险。
利用正则表达式和SQL语法知识检测
- 正则表达式:
- 可以使用正则表达式匹配常见的SQL关键字,如
SELECT
、INSERT
、UPDATE
、DELETE
、DROP
等,这些关键字在正常用户输入中很少出现,若出现在参数值中可能存在风险。例如:
- 可以使用正则表达式匹配常见的SQL关键字,如
import re
sql_keywords_pattern = re.compile(r'\b(SELECT|INSERT|UPDATE|DELETE|DROP)\b', re.IGNORECASE)
def check_sql_injection_with_regex(input_str):
if sql_keywords_pattern.search(input_str):
return True
return False
- SQL语法知识:
- 不同数据库对SQL语法的支持有细微差别,例如MySQL支持反引号 (`) 来引用表名和列名,而Oracle使用双引号 (")。可以根据不同数据库类型构建不同的检测规则。
- 例如,检测单引号、双引号的使用情况,因为SQL注入常通过闭合引号来改变SQL语句结构。
def check_quotes(input_str):
single_quote_count = input_str.count("'")
double_quote_count = input_str.count('"')
if single_quote_count % 2 != 0 or double_quote_count % 2 != 0:
return True
return False
对不同数据库类型的兼容性
- 配置文件:创建一个配置文件,记录不同数据库类型对应的SQL语法特性和检测规则。例如:
[MySQL]
quote_characters = `,'
keywords = SELECT,INSERT,UPDATE,DELETE,DROP,CREATE,ALTER
[Oracle]
quote_characters = ", '
keywords = SELECT,INSERT,UPDATE,DELETE,DROP,CREATE,ALTER
- 动态加载规则:根据用户指定的数据库类型或者从Web应用的配置中获取数据库类型,动态加载相应的检测规则。
import configparser
def load_rules(database_type):
config = configparser.ConfigParser()
config.read('database_rules.ini')
keywords = config.get(database_type, 'keywords').split(',')
quote_characters = config.get(database_type, 'quote_characters')
# 构建相应的正则表达式和检测逻辑
return keywords, quote_characters
代码框架示例
import re
class SQLInjectionDetector:
def __init__(self, database_type):
self.keywords, self.quote_characters = self.load_rules(database_type)
self.keywords_pattern = re.compile(r'\b(' + '|'.join(self.keywords) + r')\b', re.IGNORECASE)
@staticmethod
def load_rules(database_type):
config = configparser.ConfigParser()
config.read('database_rules.ini')
keywords = config.get(database_type, 'keywords').split(',')
quote_characters = config.get(database_type, 'quote_characters')
return keywords, quote_characters
def check_sql_injection(self, input_str):
if self.keywords_pattern.search(input_str):
return True
quote_count = {char: input_str.count(char) for char in self.quote_characters}
for count in quote_count.values():
if count % 2 != 0:
return True
return False
使用示例:
detector = SQLInjectionDetector('MySQL')
input_str = "1; DROP TABLE users;"
if detector.check_sql_injection(input_str):
print("可能存在SQL注入风险")
else:
print("未检测到SQL注入风险")