File size: 3,085 Bytes
c7d16a3
af86f12
 
 
c7d16a3
af86f12
 
 
b526fd8
af86f12
 
 
 
 
 
 
 
c7d16a3
af86f12
 
c7d16a3
af86f12
c7d16a3
af86f12
 
 
c7d16a3
af86f12
 
 
 
 
 
 
 
 
f21d834
af86f12
 
 
 
 
f21d834
af86f12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import pandas as pd
import os
from datetime import datetime
import joblib  # 確保有安裝此套件

# --- 全域變數與模型載入 ---
global system_weights
system_weights = {"ow": 0, "gw": 0, "tw": 0}

# 嘗試載入您的 HDBSCAN 模型
HDBSCAN_MODEL = None
try:
    if os.path.exists('hdbscan_model.pkl'):
        HDBSCAN_MODEL = joblib.load('hdbscan_model.pkl')
        print("✅ HDBSCAN 模型載入成功")
except Exception as e:
    print(f"❌ 模型載入失敗: {e}")

# --- 新增:將系統行為映射至 Web Log 特徵 ---
def map_to_web_log_features(action, status_label):
    """
    將內部 action 轉換為訓練資料中的 Method, Path, Status 數字
    """
    method = "GET"
    path = "/usr/student"
    status_code = 200
    
    # 映射邏輯 (根據您的訓練資料截圖進行模擬)
    if action == "login_attempt":
        method = "POST"
        path = "/usr/login"
    elif "admin" in action or "manage" in action:
        path = "/usr/admin"
    elif action == "malicious_sql_injection":
        method = "DELETE"
        path = "/usr/admin/developer"
        
    # 根據狀態標籤給予初始代碼
    if "failed" in status_label:
        status_code = 401
    elif "異常" in status_label:
        status_code = 403
        
    return method, path, status_code

# --- 修改後的 check_anomaly ---
def check_anomaly(ip, account, action, log_time):
    # 如果是登入或登出,直接放行 (200)
    if action in ["login_attempt", "logout"]:
        return "success (200)"

    try:
        ow = float(system_weights.get("ow", 0))
        gw = float(system_weights.get("gw", 0))
        tw = float(system_weights.get("tw", 0))
        
        # 1. 地理位置權重攔截
        from logger_service import get_geo_level # 假設此函式存在於同檔案
        geo_level = get_geo_level(ip)
        if gw == 100 and geo_level > 0:
            return "⚠️異常_地理位置受限 (100%絕對鎖定: 僅限校內專網存取) (403)"
        elif gw >= 90 and geo_level > 1:
            return "⚠️異常_地理位置受限 (高敏感防護: 僅限校園網路與宿舍) (403)"
            
        # 2. 頻率檢查
        # (此處保留您原有的 recent_clicks 計算邏輯...)
        # if (recent_clicks + 1) > max_allowed_clicks:
        #     return f"⚠️異常_單一操作頻率過高 (403)"

        # 3. HDBSCAN 模型檢測
        if HDBSCAN_MODEL:
            # 轉換特徵
            method, path, base_code = map_to_web_log_features(action, "success")
            
            # ⚠️ 注意:這裡需要接入您當初訓練時的「特徵工程」轉換代碼 (例如 LabelEncoder 或 Scaler)
            # 範例結構:
            # features = preprocess_logic(ip, log_time, method, path, base_code)
            # result = HDBSCAN_MODEL.fit_predict(features)
            # if result[-1] == -1: return "⚠️異常_作息或行為不符 (403)"
            pass

        return "success (200)"
        
    except Exception as e:
        return f"⚠️系統錯誤: {str(e)} (500)"