在本教程中,我們將使用Python構建一個簡化的、以人工智慧為特色的SIEM日誌分析系統。我們的重點將放在日誌分析和異常檢測上。

我們將介紹如何將日誌輸入系統、如何使用輕量級機器學習模型檢測異常,甚至觸及系統如何自動回應。

這個實際概念證明將說明人工智慧如何可以以實用、易於理解的方式增強安全監控。

目錄

什么是SIEM系统?

安全信息和事件管理(SIEM)系统是现代安全运营的中枢神经系统。SIEM系统汇总和关联来自IT环境各个部分的安全日志和事件,提供对潜在事件的实时洞察。这有助于组织更快地检测威胁并更早地做出响应。

这些系统汇总大量的日志数据 — 从防火墙警报到应用程序日志 — 并分析这些数据以寻找问题迹象。在这种情况下,异常检测至关重要,日志中的异常模式可能会揭示通过静态规则可能会被忽略的事件。例如,网络请求突然激增可能表明DDoS攻击,而多次登录失败尝试可能指向未经授权的访问企图。

AI 將 SIEM 能力提升到一個新層次。通過利用先進的 AI 模型(如大型語言模型),一個 AI 驅動的 SIEM 可以智能地解析和解釋日誌,學習什麼是「正常」行為,並標記出需要注意的「異常」情況。

簡而言之,AI 可以作為分析師的智能副駕駛,發現微妙的異常,甚至用簡單的語言總結發現的結果。最近在大型語言模型方面的進展使 SIEM 能夠像人類分析師一樣對無數數據點進行推理——但速度和規模遠超過人類。其結果是一個強大的數位安全助手,幫助穿透噪音,專注於真正的威脅。

前提條件

在我們深入之前,請確保您擁有以下條件:

  • 系統上安裝 Python 3.x。代碼示例應該能在任何近期的 Python 版本中運行。

  • 對 Python 程式設計(循環、函數、使用庫)的基本熟悉,以及對日誌的理解(例如,日誌條目是什麼樣的)將是有幫助的。

  • Python 庫:我們將使用一些常用的輕量級庫,不需要特殊硬件:

    • pandas 用於基本數據處理(如果您的日誌以 CSV 或類似格式存在)。

    • numpy 用於數值運算。

    • scikit-learn 用於異常檢測模型(具體來說,我們將使用 IsolationForest 算法)。

  • 要分析的一組日誌數據。您可以使用任何純文本或CSV格式的日誌文件(系統日誌,應用程序日誌等)。為了演示,我們將模擬一個小的日誌數據集,這樣即使沒有現成的日誌文件,您也可以跟著進行。

注意: 如果您沒有上述庫,請通過pip安裝它們:

pip install pandas numpy scikit-learn

設置項目

讓我們設置一個簡單的項目結構。為這個SIEM異常檢測項目創建一個新目錄並進入其中。在內部,您可以有一個Python腳本(例如,siem_anomaly_demo.py)或一個Jupyter Notebook來逐步運行代碼。

確保您的工作目錄包含或可以訪問您的日誌數據。如果您使用日誌文件,將副本放在此項目文件夾中可能是一個好主意。對於我們的概念證明,因為我們將生成合成的日誌數據,我們將不需要外部文件 – 但在實際情況下,您可能會需要。

項目設置步驟:

  1. 初始化環境 – 如果您喜歡,為此項目創建一個虛擬環境(可選但是良好的做法):

     python -m venv venv
     source venv/bin/activate  # 在Windows上使用 "venv\Scripts\activate"
    

    然後在這個虛擬環境中安裝所需的套件。

  2. 準備資料來源 – 確定您想要分析的日誌來源。這可以是日誌文件或數據庫的路徑。確保您知道日誌的格式(例如,它們是逗號分隔、JSON行還是純文本?)。為了說明,我們將捏造一些日誌條目。

  3. 設置您的腳本或筆記本 – 打開您的Python文件或筆記本。我們將從導入必要的庫和設置任何配置(例如,為了可重現性設置隨機種子)開始。

在此設置完成時,您應該已經準備好運行我們的SIEM日誌分析代碼的Python環境,並且要么有一個真實的日誌數據集,要么有意與我一起模擬數據。

實施日誌分析

在完整的SIEM系統中,日誌分析涉及從各種來源收集日誌並將它們解析為統一格式以進行進一步處理。日誌通常包含時間戳、嚴重級別、來源、事件消息、用戶ID、IP地址等字段。第一個任務是接收和預處理這些日誌。

1. 日誌接收

如果您的日誌在文本文件中,您可以在Python中讀取它們。例如,如果每個日誌條目都是文件中的一行,您可以這樣做:

with open("my_logs.txt") as f:
    raw_logs = f.readlines()

如果日誌是結構化的(比如,具有列的CSV格式),Pandas可以大大簡化讀取:

import pandas as pd
df = pd.read_csv("my_logs.csv")
print(df.head())

這將給您一個組織在列中的日誌條目的DataFrame df。但是許多日誌是半結構化的(例如,由空格或特殊字符分隔的組件)。在這種情況下,您可能需要通過定界符拆分每行或使用正則表達式提取字段。例如,想像一個日誌行:

2025-03-06 08:00:00, INFO, User login success, user: admin

這個行有一個時間戳、一個日誌級別、一個消息和一個用戶。我們可以使用Python的字符串方法解析這樣的行:

logs = [
    "2025-03-06 08:00:00, INFO, User login success, user: admin",
    "2025-03-06 08:01:23, INFO, User login success, user: alice",
    "2025-03-06 08:02:45, ERROR, Failed login attempt, user: alice",
    # ...(更多日誌行)
]
parsed_logs = []
for line in logs:
    parts = [p.strip() for p in line.split(",")]
    timestamp = parts[0]
    level = parts[1]
    message = parts[2]
    user = parts[3].split(":")[1].strip() if "user:" in parts[3] else None
    parsed_logs.append({"timestamp": timestamp, "level": level, "message": message, "user": user})

# 轉換為DataFrame以便更輕鬆地進行分析
df_logs = pd.DataFrame(parsed_logs)
print(df_logs.head())

運行上面的示例列表將輸出類似於:

            timestamp  level                 message   user
0  2025-03-06 08:00:00   INFO    User login success   admin
1  2025-03-06 08:01:23   INFO    User login success   alice
2  2025-03-06 08:02:45  ERROR  Failed login attempt   alice
...

現在我們已將日誌結構化為表格。在實際情況下,您將繼續解析日誌中的所有相關字段(例如IP地址、錯誤代碼等),具體取決於您想要分析的內容。

2. 預處理和特徵提取

將日誌轉換為結構化格式後,下一步是為異常檢測推導特徵。單獨的原始日誌消息(字符串)很難直接讓算法學習。我們通常提取可以量化的數值特徵或分類。一些特徵的例子包括:

  • 事件計數:每分鐘/每小時的事件數、每個用戶的登錄失敗次數等。

  • 持續時間或大小:如果日誌包含持續時間或數據大小(例如文件傳輸大小、查詢執行時間),則這些數值可以直接使用。

  • 分類編碼:日誌級別(INFO、ERROR、DEBUG)可以映射為數字,或者特定事件類型可以進行獨熱編碼。

在這個概念驗證中,讓我們專注於一個簡單的數值特徵:給定使用者每分鐘的登入嘗試次數。我們將模擬這個作為我們的特徵資料。

在真實系統中,您將通過按時間窗口和使用者對解析後的日誌條目進行分組來計算這一點。目標是獲得一個數字陣列,其中每個數字代表「在特定一分鐘內發生了多少次登入嘗試」。大多數情況下,這個數字會很低(正常行為),但如果某個特定分鐘看到了異常高的嘗試次數,那就是一個異常(可能是暴力攻擊)。

為了模擬,我們將生成一個包含50個值代表正常行為的列表,然後附加一些異常高的值:

import numpy as np

# 模擬50分鐘的正常登入嘗試次數(平均每分鐘約5次)
np.random.seed(42)  # 為了可重現的例子
normal_counts = np.random.poisson(lam=5, size=50)

# 模擬異常:登入嘗試激增(例如,攻擊者在一分鐘內嘗試30次以上)
anomalous_counts = np.array([30, 40, 50])

# 結合數據
login_attempts = np.concatenate([normal_counts, anomalous_counts])
print("Login attempts per minute:", login_attempts)

當您運行上述代碼時,login_attempts 可能看起來像:

Login attempts per minute: [ 5  4  4  5  5  3  5  ...  4 30 40 50]

大多數值在個位數,但最後我們有三個分鐘的嘗試次數分別為30、40和50次 – 顯而易見的異常值。這是我們為異常檢測準備的數據。在實際的日誌分析中,這種數據可能來自於隨時間計算日誌中的事件或從日誌內容中提取一些指標。

現在我們的數據已準備就緒,我們可以繼續建立異常檢測模型。

如何建立异常检测模型

为了检测日志衍生数据中的异常,我们将采用机器学习方法。具体来说,我们将使用孤立森林-一种流行的无监督异常检测算法。

孤立森林通过随机划分数据并隔离点来工作。异常值是那些很快被孤立(与其他点分开)的点,也就是在较少的随机分割中。这使其非常适合识别数据集中的异常值,而无需任何标签(我们不必预先知道哪些日志条目是“不良”的)。

为什么选择孤立森林?

  • 它高效,即使我们有大量数据也能很好地工作。

  • 它不假设任何特定的数据分布(不同于某些统计方法)。

  • 它为我们提供了一种直观的评分异常的方法。

让我们在我们的login_attempts数据上训练一个孤立森林:

from sklearn.ensemble import IsolationForest

# 準備數據使模型期望的形狀(樣本,特徵)
X = login_attempts.reshape(-1, 1)  # 每個樣本是一維 [count]

# 初始化孤立森林模型
model = IsolationForest(contamination=0.05, random_state=42)
# 污染=0.05 意味著我們預計約有5%的數據是異常值

# 在數據上訓練模型
model.fit(X)

代碼的一些注意事項:

  • 我們將login_attempts重塑為一個具有一個特徵列的二維數組X,因為scikit-learn要求用於訓練(fit)的二維數組。

  • 我們設置contamination=0.05以提示模型,大約有5%的數據可能是異常值。在我們的合成數據中,我們添加了53個點中的3個異常值,約為5.7%,因此5%是一個合理的猜測。(如果您不指定污染,該算法將根據假設選擇默認值,或者在某些版本中使用默認值0.1。)

  • random_state=42 只是確保可再現性。

到目前為止,孤立森林模型已經在我們的數據上訓練過。在內部,它構建了一個隨機樹的集合來對數據進行劃分。那些難以孤立的點(即正常點的密集群)會位於這些樹的深處,而容易被孤立的點(即異常值)會有較短的路徑。

接下來,我們將使用這個模型來識別哪些數據點被視為異常值。

測試和可視化結果

現在來到令人興奮的部分:使用我們訓練過的模型來檢測日誌數據中的異常值。我們將讓模型為每個數據點預測標籤,然後過濾掉被標記為異常值的數據點。

# 使用模型預測異常值
labels = model.predict(X)
# 模型輸出+1表示正常點,-1表示異常值

# 提取異常值的索引和值
anomaly_indices = np.where(labels == -1)[0]
anomaly_values = login_attempts[anomaly_indices]

print("Anomaly indices:", anomaly_indices)
print("Anomaly values (login attempts):", anomaly_values)

在我們的情況下,我們期望異常值是我們插入的大數字(30、40、50)。輸出可能如下所示:

Anomaly indices: [50 51 52]
Anomaly values (login attempts): [30 40 50]

即使不知道具體有關“登錄嘗試”的任何信息,孤立森林也將這些值識別為與其他數據不符。

這就是在安全情境中異常檢測的威力:我們並不總是知道一個新攻擊會是怎樣的,但如果它導致某件事遠離正常模式(比如一個用戶突然比平常多做了10倍的登錄嘗試),異常檢測器就會照亮它。

視覺化結果

在實際分析中,通常將數據和異常視覺化是很有用的。例如,我們可以將login_attempts值隨時間(每分鐘)繪製成圖,並使用不同顏色突出顯示異常。

在這個簡單案例中,一個折線圖會顯示大部分時間登錄率保持在每分鐘3-8次之間,最後有三個巨大的尖峰。這些尖峰就是我們的異常。如果你在筆記本中運行,可以用Matplotlib實現這一點:

import matplotlib.pyplot as plt

plt.plot(login_attempts, label="Login attempts per minute")
plt.scatter(anomaly_indices, anomaly_values, color='red', label="Anomalies")
plt.xlabel("Time (minute index)")
plt.ylabel("Login attempts")
plt.legend()
plt.show()

對於這裡的文本輸出,已經確認高值已被檢測到。在更複雜的情況下,異常檢測模型還為每個點提供一個異常分數(例如,它與正常範圍的距離)。例如,Scikit-learn的IsolationForest具有一個decision_function方法,可以生成一個分數(分數越低意味著更異常)。

為了簡單起見,我們這裡不深入討論分數,但知道你可以檢索它們以按嚴重性對異常進行排名是很有幫助的。

異常檢測工作正常運作後,當我們發現異常時可以採取什麼行動呢?這讓我們開始思考自動響應。

自動響應可能性

偵測異常只是戰鬥的一半 — 下一步是對其做出回應。在企業SIEM系統中,自動化回應(通常與SOAR – 安全編排、自動化和回應相關)可以顯著減少對事件的反應時間。

當AI動力的SIEM標記出異常情況時,可以採取哪些行動呢?以下是一些可能性:

  • 警報: 最簡單的行動是向安全人員發送警報。這可以是一封電子郵件、Slack消息,或在事件管理系統中創建一個工單。警報將包含異常情況的詳細信息(例如,“用戶alice在1分鐘內出現了50次登錄失敗的嘗試,這是異常的”)。GenAI可以通過為分析師生成一個清晰的自然語言摘要來幫助這裡。

  • 自動化緩解:更先進的系統可能會採取直接行動。例如,如果日誌中顯示某個IP地址展現惡意行為,系統可以自動在防火牆上封鎖該IP。在我們的登錄高峰示例中,系統可能會暫時鎖定使用者帳戶或要求進行額外的身分驗證,假設可能是機器人攻擊。基於人工智能的SIEM今天確實可以在檢測到特定威脅時觸發預定義的響應動作,甚至在檢測到特定威脅時編排複雜的工作流程(有關更多信息,請參考AI SIEM: How SIEM with AI/ML is Revolutionizing the SOC | Exabeam)。

  • 調查支援:生成式AI也可以用於自動收集上下文信息。例如,在檢測到異常情況時,系統可以提取相關日誌(周圍事件、同一用戶或同一IP的其他操作)並提供匯總報告。這可以幫助分析人員避免手動查詢多個數據來源。

實施自動回應時要小心 — 你不希望系統對誤報作出過度反應。一個常見的策略是分層回應: 低信心的異常可能只需記錄警告或發送低優先級警報,而高信心的異常(或異常的組合)將觸發主動防禦措施。

在實踐中,基於人工智慧的SIEM將與您的基礎設施整合(通過API、腳本等)以執行這些操作。對於我們的Python PoC,您可以模擬當檢測到異常時進行自動回應,比如打印一條消息或調用一個虛擬函數。例如:

if len(anomaly_indices) > 0:
    print(f"Alert! Detected {len(anomaly_indices)} anomalous events. Initiating response procedures...")
    # 在這裡,您可以添加代碼來禁用用戶或通知管理員等。

雖然我們的演示很簡單,但很容易想像將其擴展。例如,SIEM可以將異常輸入到一個更大的生成模型中,該模型評估情況並決定最佳操作方式(比如一個了解您運營手冊的聊天機器人助手)。隨著人工智慧變得更加複雜,自動化的可能性正在擴大。

結論

在本教程中,我們構建了一個基本的基於人工智慧的SIEM組件,該組件接收日誌數據,使用機器學習模型進行異常分析,並識別可能代表安全威脅的異常事件。

我們從解析和準備日誌數據開始,然後使用孤立森林模型來檢測登錄嘗試次數流中的異常值。該模型成功地標記了不正常的行為,而沒有任何關於“攻擊”外觀的先前知識 — 它純粹依賴於與學習到的正常模式的偏差。

我們還討論了這樣一個系統如何應對檢測到的異常情況,從警報人員到自動採取行動。

搭配AI/ML的現代SIEM系統正在朝著這個方向發展:它們不僅可以檢測問題,還可以幫助分類和應對。生成式AI進一步增強了這一點,通過從分析人員學習並提供智能摘要和決策,有效地成為安全運營中心中不倦的助手。

下一步和改進方向:

  • 您可以嘗試在真實的日誌數據上運用這種方法。例如,取一個系統日誌文件,提取一個特徵,比如“每小時錯誤日誌數”或“每個會話傳輸的字節數”,然後對其運行異常檢測。

  • 試驗其他算法,比如單類SVM或局部異常因子用於異常檢測,看看它們之間的比較。

  • 引入一個簡單的語言模型來解析日誌行或解釋異常情況。例如,一個LLM可以讀取一個異常的日誌條目並建議可能出了什麼問題(“這個錯誤通常意味著數據庫無法訪問”)。

  • 擴展功能:在一個真正的SIEM中,您可以同時使用多個信號(失敗登錄次數、不尋常的IP地理位置、日誌中罕見的進程名稱等)。增加更多功能和數據可以改善檢測的上下文。