Safesql V1
S
Safesql V1
由 deathsaber93 开发
基于Keras 3.x训练的恶意SQL检测模型,能识别多种SQL注入攻击向量
下载量 41
发布时间 : 6/16/2024
模型简介
专门用于检测恶意SQL的模型,能识别包括基于错误的注入、联合查询注入、盲注等多种SQL注入攻击方式。
模型特点
多类型SQL注入检测
能识别多种SQL注入攻击向量,包括基于错误的注入、联合查询注入、盲注等7种类型
高效特征工程
通过递归特征消除筛选出10个关键数值特征用于训练,提升检测效率
高级训练策略
采用预热阶段和主训练阶段的双阶段学习率调整,结合特殊回调函数防止梯度爆炸
高精度检测
基准测试显示99.76%的准确率,误报率仅0.03%
模型能力
SQL注入检测
恶意SQL识别
文本分类
使用案例
网络安全
Web应用防火墙
集成到WAF中实时检测SQL注入攻击
99.76%的检测准确率
数据库审计
监控数据库查询日志中的可疑SQL语句
0.61%的漏报率
🚀 SafeSQL-v1 (在线演示)
SafeSQL-v1是一个专门用于检测恶意SQL的Keras 3.x模型。它能检测多种SQL注入向量,为数据库安全保驾护航。
✨ 主要特性
- 能够检测多种SQL注入向量,如基于错误、联合、盲注、布尔、时间、带外和堆叠查询等类型。
- 基于约167K条SQL数据进行训练,恶意和良性SQL分布近乎均匀。
- 采用特殊的预处理和特征选择方法,训练过程中使用了学习率调整和梯度爆炸保护机制。
- 应用了权重和内核约束,防止过拟合,提高泛化能力。
- 使用混合精度技术,加快模型加载和推理速度。
📦 安装指南
- 根据你的硬件情况(是否使用GPU),下载相应的
requiremnts-[cpu/gpu].txt
文件并安装:
pip install -r requirements.txt
- 下载模型文件
sqid.keras
。
💻 使用示例
基础用法
import re
from multiprocessing import cpu_count
from keras.src.saving import load_model
import pandas as pd
from numpy import int64
from pandarallel import pandarallel
from sklearn.preprocessing import RobustScaler
model = load_model('./sqid.keras')
pandarallel.initialize(use_memory_fs=True, nb_workers=cpu_count())
def sql_tokenize(sql_query):
sql_query = sql_query.replace('`', ' ').replace('%20', ' ').replace('=', ' = ').replace('((', ' (( ').replace(
'))', ' )) ').replace('(', ' ( ').replace(')', ' ) ').replace('||', ' || ').replace(',', '').replace(
'--', ' -- ').replace(':', ' : ').replace('%23', ' # ').replace('+', ' + ').replace('!=',
' != ') \
.replace('"', ' " ').replace('%26', ' and ').replace('$', ' $ ').replace('%28', ' ( ').replace('%2A', ' * ') \
.replace('%7C', ' | ').replace('&', ' & ').replace(']', ' ] ').replace('[', ' [ ').replace(';',
' ; ').replace(
'/*', ' /* ')
sql_reserved = {'SELECT', 'FROM', 'WHERE', 'AND', 'OR', 'NOT', 'IN', 'LIKE', 'ORDER', 'BY', 'GROUP', 'HAVING',
'LIMIT', 'BETWEEN', 'IS', 'NULL', '%', 'LIKE', 'MIN', 'MAX', 'AS', 'UPPER', 'LOWER', 'TO_DATE',
'=', '>', '<', '>=', '<=', '!=', '<>', 'BETWEEN', 'LIKE', 'EXISTS', 'JOIN', 'UNION', 'ALL',
'ASC', 'DESC', '||', 'AVG', 'LIMIT', 'EXCEPT', 'INTERSECT', 'CASE', 'WHEN', 'THEN', 'IF',
'IF', 'ANY', 'CAST', 'CONVERT', 'COALESCE', 'NULLIF', 'INNER', 'OUTER', 'LEFT', 'RIGHT', 'FULL',
'CROSS', 'OVER', 'PARTITION', 'SUM', 'COUNT', 'WITH', 'INTERVAL', 'WINDOW', 'OVER',
'ROW_NUMBER', 'RANK',
'DENSE_RANK', 'NTILE', 'FIRST_VALUE', 'LAST_VALUE', 'LAG', 'LEAD', 'DISTINCT', 'COMMENT',
'INSERT',
'UPDATE', 'DELETED', 'MERGE', '*', 'generate_series', 'char', 'chr', 'substr', 'lpad',
'extract',
'year', 'month', 'day', 'timestamp', 'number', 'string', 'concat', 'INFORMATION_SCHEMA',
"SQLITE_MASTER", 'TABLES', 'COLUMNS', 'CUBE', 'ROLLUP', 'RECURSIVE', 'FILTER', 'EXCLUDE',
'AUTOINCREMENT', 'WITHOUT', 'ROWID', 'VIRTUAL', 'INDEXED', 'UNINDEXED', 'SERIAL',
'DO', 'RETURNING', 'ILIKE', 'ARRAY', 'ANYARRAY', 'JSONB', 'TSQUERY', 'SEQUENCE',
'SYNONYM', 'CONNECT', 'START', 'LEVEL', 'ROWNUM', 'NOCOPY', 'MINUS', 'AUTO_INCREMENT', 'BINARY',
'ENUM', 'REPLACE', 'SET', 'SHOW', 'DESCRIBE', 'USE', 'EXPLAIN', 'STORED', 'VIRTUAL', 'RLIKE',
'MD5', 'SLEEP', 'BENCHMARK', '@@VERSION', 'VERSION', '@VERSION', 'CONVERT', 'NVARCHAR', '#',
'##', 'INJECTX',
'DELAY', 'WAITFOR', 'RAND',
}
tokens = sql_query.split()
tokens = [re.sub(r"""[^*\w\s.=\-><_|()!"']""", '', token) for token in tokens]
for i, token in enumerate(tokens):
if token.strip().upper() in sql_reserved:
continue
if token.strip().isnumeric():
tokens[i] = '#NUMBER#'
elif re.match(r'^[a-zA-Z_.|][a-zA-Z0-9_.|]*$', token.strip()):
tokens[i] = '#IDENTIFIER#'
elif re.match(r'^[\d:]*$', token.strip()):
tokens[i] = '#TIMESTAMP#'
elif '%' in token.strip():
tokens[i] = ' '.join(
[j.strip() if j.strip() in ('%', "'", "'") else '#IDENTIFIER#' for j in token.strip().split('%')])
return ' '.join(tokens)
def add_features(x):
s = ["num_tables", "num_columns", "num_literals", "num_parentheses", "has_union", "depth_nested_queries", "num_join", "num_sp_chars", "has_mismatched_quotes", "has_tautology"]
x['Query'] = x['Query'].copy().parallel_apply(lambda a: sql_tokenize(a))
x['num_tables'] = x['Query'].str.lower().str.count(r'FROM\s+#IDENTIFIER#', flags=re.I)
x['num_columns'] = x['Query'].str.lower().str.count(r'SELECT\s+#IDENTIFIER#', flags=re.I)
x['num_literals'] = x['Query'].str.lower().str.count("'[^']*'", flags=re.I) + x['Query'].str.lower().str.count(
'"[^"]"', flags=re.I)
x['num_parentheses'] = x['Query'].str.lower().str.count("\\(", flags=re.I) + x['Query'].str.lower().str.count(
'\\)',
flags=re.I)
x['has_union'] = x['Query'].str.lower().str.count(" union |union all", flags=re.I) > 0
x['has_union'] = x['has_union'].astype(int64)
x['depth_nested_queries'] = x['Query'].str.lower().str.count("\\(", flags=re.I)
x['num_join'] = x['Query'].str.lower().str.count(
" join |inner join|outer join|full outer join|full inner join|cross join|left join|right join",
flags=re.I)
x['num_sp_chars'] = x['Query'].parallel_apply(lambda a: len(re.findall(r'[\'";\-*/%=><|#]', a)))
x['has_mismatched_quotes'] = x['Query'].parallel_apply(
lambda sql_query: 1 if re.search(r"'.*[^']$|\".*[^\"]$", sql_query) else 0)
x['has_tautology'] = x['Query'].parallel_apply(lambda sql_query: 1 if re.search(r"'[\s]*=[\s]*'", sql_query) else 0)
return x
input_sqls = ['SELECT roomName , RoomId FROM Rooms WHERE basePrice > 160 AND maxOccupancy > 2;', # 非恶意
"ORDER BY 1,SLEEP(5),BENCHMARK(1000000,MD5('A')),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18#", # 恶意
"; desc users; --", # 恶意
"ORDER BY 1,SLEEP(5),BENCHMARK(1000000,MD5('A')),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27", # 恶意
"SELECT DISTINCT t2.datasetid FROM paperdataset AS t3 JOIN dataset AS t2 ON t3.datasetid = t2.datasetid JOIN paperkeyphrase AS t1 ON t1.paperid = t3.paperid JOIN keyphrase AS t4 ON t1.keyphraseid = t4.keyphraseid WHERE t4.keyphrasename = ""semantic parsing"";" # 非恶意
]
numeric_features = ["num_tables", "num_columns", "num_literals", "num_parentheses", "has_union", "depth_nested_queries", "num_join", "num_sp_chars", "has_mismatched_quotes", "has_tautology"]
input_df = pd.DataFrame(input_sqls, columns=['Query'])
input_df = add_features(input_df)
scaler = RobustScaler()
x_in = scaler.fit_transform(input_df[numeric_features])
preds = model.predict([input_df['Query'], x_in]).tolist()
for i, pred in enumerate(preds):
print()
print(f'查询语句: {input_sqls[i]}')
print(f'是否为恶意: {pred[0] >= 0.50} ({pred[0]})')
print()
# 运行基准测试
input_df = pd.read_csv('benchmark.csv')
hits = 0
data_size = input_df.shape[0]
miss_pos, miss_neg = [], []
total_negs = input_df[input_df['Label'] == 1.0].shape[0]
total_pos = input_df[input_df['Label'] == 0.0].shape[0]
pred_trans = ['良性', '恶意']
false_metrics = {0: 0, 1: 0}
x_in = scaler.transform(input_df[numeric_features])
print('正在运行基准测试')
preds = model.predict([input_df['Query'], x_in])
miss_q = []
actuals = input_df['Label'].tolist()
for i, pred in enumerate(preds):
pred = int(pred[0] > .95)
if pred == actuals[i]:
hits += 1
else:
false_metrics[int(pred)] += 1
print('基准测试完成。')
print('正在打印结果。')
acc = round((hits / data_size) * 100, 2)
f_neg = round((false_metrics[0] / total_negs) * 100, 2)
f_pos = round((false_metrics[1] / total_pos) * 100, 2)
print(f'总数据量: {data_size}')
print(f'负样本总数: {total_negs} \t 正样本总数: {total_pos}')
print()
print(f'命中总数: {hits}/{data_size},准确率为 {acc}%。')
print(f'假阴性: {false_metrics[0]}({f_neg}%) \t 假阳性: {false_metrics[1]}({f_pos}%)')
🔧 技术细节
- 训练数据:使用了约167K条SQL数据,包含恶意和良性SQL,分布近乎均匀。数据来源包括多个公开数据集,如 b-mc2/sql-create-context、philikai/Spider-SQL-LLAMA2_train 等。
- 预处理:对SQL数据进行了特殊的预处理,使用了特殊的掩码标记。同时生成了28个额外的数值特征,并使用递归特征消除方法选择了前10个特征进行训练。
- 训练过程:训练过程分为热身阶段和主训练阶段。热身阶段使用较小的、正弦衰减的学习率,主训练阶段使用较高的学习率和余弦衰减。使用了特殊的回调函数来监测和防止梯度爆炸,并根据爆炸规模自动调整学习率和模型权重。
- 模型约束:应用了权重和内核约束,帮助防止过拟合,提高模型的泛化能力。
- 混合精度:使用 混合精度 技术,加快模型加载和推理速度。
📚 详细文档
模型元信息
属性 | 详情 |
---|---|
反馈邮箱 | aakash.howlader@gmail.com |
模型类型 | 语言模型 |
支持语言 | 英语 |
许可证 | Apache 2.0 |
在线演示 | SafeSQL-v1-Demo |
检查点信息
823/823 ━━━━━━━━━━━━━━━━━━━━ 99s 120ms/step - AUPR: 0.9979 - f1_score: 0.5782 - fn: 64.0947 - fp: 8.2500 - loss: 0.0236 - precision: 0.9987 - recall: 0.9889 - val_AUPR: 0.9970 - val_f1_score: 0.5775 - val_fn: 34.0000 - val_fp: 4.0000 - val_loss: 0.0298 - val_precision: 0.9985 - val_recall: 0.9873 - learning_rate: 7.0911e-04
基准测试结果
- 总SQL数量:30919
- 总负样本数量:11382
- 总正样本数量:19537
- 命中总数:30844/30919,准确率为 99.76%
- 假阴性数量:69(0.61%)
- 假阳性数量:6(0.03%)
训练数据和基准测试数据
- 训练数据:dataset/train.csv
- 基准测试数据:dataset/benchmark.csv
📄 许可证
本模型使用 Apache 2.0 许可证。
架构图
Distilbert Base Uncased Finetuned Sst 2 English
Apache-2.0
基于DistilBERT-base-uncased在SST-2情感分析数据集上微调的文本分类模型,准确率91.3%
文本分类 英语
D
distilbert
5.2M
746
Xlm Roberta Base Language Detection
MIT
基于XLM-RoBERTa的多语言检测模型,支持20种语言的文本分类
文本分类
Transformers 支持多种语言

X
papluca
2.7M
333
Roberta Hate Speech Dynabench R4 Target
该模型通过动态生成数据集来改进在线仇恨检测,专注于从最差案例中学习以提高检测效果。
文本分类
Transformers 英语

R
facebook
2.0M
80
Bert Base Multilingual Uncased Sentiment
MIT
基于bert-base-multilingual-uncased微调的多语言情感分析模型,支持6种语言的商品评论情感分析
文本分类 支持多种语言
B
nlptown
1.8M
371
Emotion English Distilroberta Base
基于DistilRoBERTa-base微调的英文文本情感分类模型,可预测埃克曼六种基本情绪及中性类别。
文本分类
Transformers 英语

E
j-hartmann
1.1M
402
Robertuito Sentiment Analysis
基于RoBERTuito的西班牙语推文情感分析模型,支持POS(积极)/NEG(消极)/NEU(中性)三类情感分类
文本分类 西班牙语
R
pysentimiento
1.0M
88
Finbert Tone
FinBERT是一款基于金融通讯文本预训练的BERT模型,专注于金融自然语言处理领域。finbert-tone是其微调版本,用于金融情感分析任务。
文本分类
Transformers 英语

F
yiyanghkust
998.46k
178
Roberta Base Go Emotions
MIT
基于RoBERTa-base的多标签情感分类模型,在go_emotions数据集上训练,支持28种情感标签识别。
文本分类
Transformers 英语

R
SamLowe
848.12k
565
Xlm Emo T
XLM-EMO是一个基于XLM-T模型微调的多语言情感分析模型,支持19种语言,专门针对社交媒体文本的情感预测。
文本分类
Transformers 其他

X
MilaNLProc
692.30k
7
Deberta V3 Base Mnli Fever Anli
MIT
基于MultiNLI、Fever-NLI和ANLI数据集训练的DeBERTa-v3模型,擅长零样本分类和自然语言推理任务
文本分类
Transformers 英语

D
MoritzLaurer
613.93k
204
精选推荐AI模型
Llama 3 Typhoon V1.5x 8b Instruct
专为泰语设计的80亿参数指令模型,性能媲美GPT-3.5-turbo,优化了应用场景、检索增强生成、受限生成和推理任务
大型语言模型
Transformers 支持多种语言

L
scb10x
3,269
16
Cadet Tiny
Openrail
Cadet-Tiny是一个基于SODA数据集训练的超小型对话模型,专为边缘设备推理设计,体积仅为Cosmo-3B模型的2%左右。
对话系统
Transformers 英语

C
ToddGoldfarb
2,691
6
Roberta Base Chinese Extractive Qa
基于RoBERTa架构的中文抽取式问答模型,适用于从给定文本中提取答案的任务。
问答系统 中文
R
uer
2,694
98