【CCF2022】Web攻擊檢測與分類識別 baseline

線下cv acc:0.97 線上 應該0.6+

1 賽題介紹

賽題名稱
Web攻擊檢測與分類識別

賽程規劃
參賽報名:2022年8月20日(10點)-10月10日(24點)
線上參賽:2022年8月27日(10點)-10月16日(24點)
復現提交:2022年10月17日-10月23日(16點前)
代碼審覈:2022年10月24日-2022年11月2日
公佈晉級:2022年11月3日-2022年11月6日
決賽答辯:2022年11月18日(暫定)

賽題背景
某業務平臺平均每月捕獲到Web攻擊數量超過2億,涉及常見注入攻擊,代碼執行等類型。傳統威脅檢測手段通過分析已知攻擊特徵進行規則匹配,無法檢測未知漏洞或攻擊手法。如何快速準確地識別未知威脅攻擊並且將不同攻擊正確分類,對提升Web攻擊檢測能力至關重要。利用機器學習和深度學習技術對攻擊報文進行識別和分類已經成爲解決該問題的創新思路,有利於推動AI技術在威脅檢測分析場景的研究與應用。

賽題任務
參賽團隊需要對前期提供的訓練集進行分析,通過特徵工程、機器學習和深度學習等方法構建AI模型,實現對每一條樣本正確且快速分類,不斷提高模型精確率和召回率。待模型優化穩定後,通過無標籤測試集評估各參賽團隊模型分類效果,以正確率評估各參賽團隊模型質量。

2 數據簡介

數據簡介
賽題訓練集分爲6種不同標籤,共計約3.5萬條數據。訓練數據集字段內容主要包括:
● lable:攻擊類型編號
● 其他:HTTP協議內容

LGM基線

導入包

import lightgbm as lgb
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from lightgbm import early_stopping
from lightgbm import log_evaluation
from sklearn.decomposition import TruncatedSVD
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import LabelEncoder
from tqdm import tqdm
from user_agents import parse

數據加載

train=pd.concat([
    pd.read_csv('data/train/SQL注入.csv'),
    pd.read_csv('data/train/XSS跨站腳本.csv'),
    pd.read_csv('data/train/命令執行.csv'),
    pd.read_csv('data/train/白.csv'),
    pd.read_csv('data/train/目錄遍歷.csv'),
    pd.read_csv('data/train/遠程代碼執行.csv'),
],axis=0).reset_index(drop=True)


test=pd.read_csv('data/test.csv')

標籤分佈

train['label'].value_counts()
1,14038
2,9939
0,6489
3,1397
4,697
5,659

基礎特徵

  • 文本特徵
texts=data['user_agent'].values.tolist()
n_components = 16
tf = TfidfVectorizer(min_df= 3, max_df=0.5,analyzer = 'char_wb', ngram_range = (2,5))
X = tf.fit_transform(texts)
svd = TruncatedSVD(n_components=n_components,
                   random_state=42)
X_svd = svd.fit_transform(X)
df_tfidf = pd.DataFrame(X_svd)
df_tfidf.columns = [f'user_agent_name_tfidf_{i}' for i in range(n_components)]

  • 類別編碼
for col in tqdm(cate_cols):
    lbl = LabelEncoder()
    lbl.fit(data[col])
    data[col] = lbl.transform(data[col])

五折交叉驗證

def lgb_model(train, target, test, k):
    feats = [f for f in train.columns if f not in ['label',  'url', 'url_count']]
    #     feats=import_cols
    print('Current num of features:', len(feats))

    oof_probs = np.zeros((train.shape[0],6))
    output_preds = 0
    offline_score = []
    feature_importance_df = pd.DataFrame()
    parameters = {
        'learning_rate': 0.03,
        'boosting_type': 'gbdt',
        'objective': 'multiclass',
        'metric': 'multi_error',
        'num_class': 6,
        'num_leaves': 31,
        'feature_fraction': 0.6,
        'bagging_fraction': 0.8,
        'min_data_in_leaf': 15,
        'verbose': -1,
        'nthread': 4,
        'max_depth': 7
    }

    seeds = [2020]
    for seed in seeds:
        folds = StratifiedKFold(n_splits=k, shuffle=True, random_state=seed)
        for i, (train_index, test_index) in enumerate(folds.split(train, target)):
            train_y, test_y = target.iloc[train_index], target.iloc[test_index]
            train_X, test_X = train[feats].iloc[train_index, :], train[feats].iloc[test_index, :]

            dtrain = lgb.Dataset(train_X,
                                 label=train_y)
            dval = lgb.Dataset(test_X,
                               label=test_y)
            lgb_model = lgb.train(
                parameters,
                dtrain,
                num_boost_round=8000,
                valid_sets=[dval],
                callbacks=[early_stopping(100), log_evaluation(100)],
            )
            oof_probs[test_index] = lgb_model.predict(test_X[feats], num_iteration=lgb_model.best_iteration) / len(
                seeds)
            offline_score.append(lgb_model.best_score['valid_0']['multi_error'])
            output_preds += lgb_model.predict(test[feats],
                                              num_iteration=lgb_model.best_iteration) / folds.n_splits / len(seeds)
            print(offline_score)
            # feature importance
            fold_importance_df = pd.DataFrame()
            fold_importance_df["feature"] = feats
            fold_importance_df["importance"] = lgb_model.feature_importance(importance_type='gain')
            fold_importance_df["fold"] = i + 1
            feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)
    print('OOF-MEAN-AUC:%.6f, OOF-STD-AUC:%.6f' % (np.mean(offline_score), np.std(offline_score)))
    print('feature importance:')
    print(feature_importance_df.groupby(['feature'])['importance'].mean().sort_values(ascending=False).head(50))

    return output_preds, oof_probs, np.mean(offline_score), feature_importance_df


print('開始模型訓練train')
lgb_preds, lgb_oof, lgb_score, feature_importance_df = lgb_model(train=train[feature_names],
                                                                 target=train['label'],
                                                                 test=test[feature_names], k=5)

優化方向

  • web請求信息解析,比如user_agent/body/url,然後做統計特徵
  • 文本特徵挖掘,比如tfidf可以對char、toekn級別去做embedding,ngram參數調整下應該有分數變化

歡迎大家關注公衆號“ChallengeHub”,獲取更多開源方案

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章