Safesql V1
S
Safesql V1
Developed by deathsaber93
Keras 3.xでトレーニングされた悪意あるSQL検出モデル、複数のSQLインジェクション攻撃ベクトルを識別可能
Downloads 41
Release Time : 6/16/2024
Model Overview
悪意あるSQLを検出するために特別に設計されたモデルで、エラーベースのインジェクション、UNIONクエリインジェクション、ブラインドインジェクションなど様々なSQLインジェクション攻撃手法を識別できます。
Model Features
多種類SQLインジェクション検出
エラーベースのインジェクション、UNIONクエリインジェクション、ブラインドインジェクションなど7種類のSQLインジェクション攻撃ベクトルを識別可能
効率的な特徴量エンジニアリング
再帰的特徴量削減により10個の重要な数値特徴量を選定し、検出効率を向上
高度なトレーニング戦略
ウォームアップフェーズとメイントレーニングフェーズの二段階学習率調整を採用し、勾配爆発を防ぐ特別なコールバック関数を組み合わせ
高精度検出
ベンチマークテストで99.76%の精度、誤検知率はわずか0.03%
Model Capabilities
SQLインジェクション検出
悪意あるSQL識別
テキスト分類
Use Cases
サイバーセキュリティ
Webアプリケーションファイアウォール
WAFに統合してSQLインジェクション攻撃をリアルタイム検出
99.76%の検出精度
データベース監査
データベースクエリログ内の疑わしいSQL文を監視
0.61%の見逃し率
🚀 SafeSQL-v1 (Playground)
このモデルはKeras 3.xを使用して開発され、悪意のあるSQLを検出するために特化して訓練されています。様々なSQLインジェクションベクトルを検出でき、約167KのSQLデータを用いて訓練されています。
📦 インストール
- ハードウェア(GPUの使用の有無)に応じて、対応する
requiremnts-[cpu/gpu].txt
ファイルをダウンロードし、インストールします (pip install -r requirements.txt
)。 - モデルファイル
sqid.keras
をダウンロードします。
✨ 主な機能
- 様々なSQLインジェクションベクトル(Error-based、Union-based、Blind、Boolean-based、Time-based、Out-of-band、Stacked queries)を検出できます。
- 約167KのSQLデータを用いて訓練され、悪意のあるSQLと良性のSQLをほぼ均等に含んでいます。
- SQL用の前処理と特殊なマスキングトークンを使用して訓練されています。
- 28の追加の数値特徴量を生成し、そのうち上位10個を選択して再帰的特徴削減を用いて訓練しています。
- 学習率の調整や勾配爆発の防止に特殊なコールバックを使用しています。
- 過学習を防止し、汎化性能を向上させるために、重みとカーネルの制約を適用しています。
- 高速なモデルロードと推論のために、混合精度を使用しています。
💻 使用例
基本的な使用法
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;', # Not malicious
"ORDER BY 1,SLEEP(5),BENCHMARK(1000000,MD5('A')),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18#", # Malicious
"; desc users; --", # Malicious
"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", # Malicious
"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"";" # Not malicious
]
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'Query: {input_sqls[i]}')
print(f'Malicious? {pred[0] >= 0.50} ({pred[0]})')
print()
# Run the benchmark
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 = ['Benign', 'Malicious']
false_metrics = {0: 0, 1: 0}
x_in = scaler.transform(input_df[numeric_features])
print('Running benchmark')
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('Finished benchmark.')
print('printing results.')
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'Total data: {data_size}')
print(f'Total Negatives: {total_negs} \t Total Positives: {total_pos}')
print()
print(f'Total hits: {hits}/{data_size} with accuracy of {acc}%.')
print(f'False Negatives: {false_metrics[0]}({f_neg}%) \t False Positives: {false_metrics[1]}({f_pos}%)', false_metrics[0], f_neg, false_metrics[1], f_pos)
📚 ドキュメント
モデルメタ情報
属性 | 详情 |
---|---|
モデルタイプ | 言語モデル |
言語 (NLP) | 英語 |
ライセンス | Apache 2.0 |
プレイグラウンド | SafeSQL-v1-Demo |
フィードバック | aakash.howlader@gmail.com |
チェックポイントエポック
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%)
- 誤検知数 (False Negatives): 69 (0.61%)
- 誤検知数 (False Positives): 6 (0.03%)
訓練データ
訓練データはこちら、ベンチマークデータはこちらで入手できます。データは以下のソースから収集されています。
- https://www.kaggle.com/datasets/gambleryu/biggest-sql-injection-dataset/data
- https://huggingface.co/datasets/b-mc2/sql-create-context
- https://github.com/payloadbox/sql-injection-payload-list/tree/master/Intruder
- https://huggingface.co/datasets/ChrisHayduk/Llama-2-SQL-Dataset/viewer/default/eval
- https://huggingface.co/datasets/philikai/Spider-SQL-LLAMA2_train/viewer/default/train
ベンチマークデータ
- https://www.kaggle.com/datasets/sajid576/sql-injection-dataset?select=Modified_SQL_Dataset.csv
🔧 技術詳細
このモデルは、Keras 3.xを使用して開発され、悪意のあるSQLを検出するために特化して訓練されています。約167KのSQLデータを用いて訓練され、悪意のあるSQLと良性のSQLをほぼ均等に含んでいます。訓練には、SQL用の前処理と特殊なマスキングトークンを使用しています。また、28の追加の数値特徴量を生成し、そのうち上位10個を選択して再帰的特徴削減を用いて訓練しています。学習率の調整や勾配爆発の防止に特殊なコールバックを使用しています。過学習を防止し、汎化性能を向上させるために、重みとカーネルの制約を適用しています。高速なモデルロードと推論のために、混合精度を使用しています。
📄 ライセンス
このモデルはApache 2.0ライセンスの下で提供されています。
アーキテクチャ
Distilbert Base Uncased Finetuned Sst 2 English
Apache-2.0
DistilBERT - base - uncasedをベースに、SST - 2感情分析データセットで微調整されたテキスト分類モデル。正解率91.3%
テキスト分類 English
D
distilbert
5.2M
746
Xlm Roberta Base Language Detection
MIT
XLM-RoBERTaベースの多言語検出モデル、20言語のテキスト分類をサポート
テキスト分類
Transformers Supports Multiple Languages

X
papluca
2.7M
333
Roberta Hate Speech Dynabench R4 Target
このモデルは動的データセット生成を通じてオンライン憎悪検出を改善し、検出効果を高めるために最悪ケースから学習することに焦点を当てています。
テキスト分類
Transformers English

R
facebook
2.0M
80
Bert Base Multilingual Uncased Sentiment
MIT
bert-base-multilingual-uncasedを微調整した多言語感情分析モデルで、6言語の商品レビューの感情分析に対応しています。
テキスト分類 Supports Multiple Languages
B
nlptown
1.8M
371
Emotion English Distilroberta Base
DistilRoBERTa-baseをファインチューニングした英語テキストの感情分類モデルで、エクマンの6基本感情と中立カテゴリを予測可能。
テキスト分類
Transformers English

E
j-hartmann
1.1M
402
Robertuito Sentiment Analysis
RoBERTuitoベースのスペイン語ツイート感情分析モデル、POS(ポジティブ)/NEG(ネガティブ)/NEU(ニュートラル)の3分類に対応
テキスト分類 Spanish
R
pysentimiento
1.0M
88
Finbert Tone
FinBERTは金融通信テキストを元に事前学習されたBERTモデルで、金融自然言語処理分野に特化しています。finbert-toneはその微調整バージョンで、金融感情分析タスクに使用されます。
テキスト分類
Transformers English

F
yiyanghkust
998.46k
178
Roberta Base Go Emotions
MIT
RoBERTa-baseに基づく多ラベル感情分類モデルで、go_emotionsデータセットで訓練され、28種類の感情ラベル識別をサポートします。
テキスト分類
Transformers English

R
SamLowe
848.12k
565
Xlm Emo T
XLM-EMOはXLM-Tモデルをファインチューニングした多言語感情分析モデルで、19言語をサポートし、特にソーシャルメディアテキストの感情予測に特化しています。
テキスト分類
Transformers Other

X
MilaNLProc
692.30k
7
Deberta V3 Base Mnli Fever Anli
MIT
MultiNLI、Fever-NLI、ANLIのデータセットを用いて訓練されたDeBERTa-v3モデルで、ゼロショット分類と自然言語推論タスクに優れています。
テキスト分類
Transformers English

D
MoritzLaurer
613.93k
204
Featured Recommended AI Models
Llama 3 Typhoon V1.5x 8b Instruct
タイ語専用に設計された80億パラメータの命令モデルで、GPT-3.5-turboに匹敵する性能を持ち、アプリケーションシナリオ、検索拡張生成、制限付き生成、推論タスクを最適化
大規模言語モデル
Transformers Supports Multiple Languages

L
scb10x
3,269
16
Cadet Tiny
Openrail
Cadet-TinyはSODAデータセットでトレーニングされた超小型対話モデルで、エッジデバイス推論向けに設計されており、体積はCosmo-3Bモデルの約2%です。
対話システム
Transformers English

C
ToddGoldfarb
2,691
6
Roberta Base Chinese Extractive Qa
RoBERTaアーキテクチャに基づく中国語抽出型QAモデルで、与えられたテキストから回答を抽出するタスクに適しています。
質問応答システム Chinese
R
uer
2,694
98