在當前數位化轉型加速的時代背景下,網路安全威脅的複雜程度與攻擊手法的多樣性正呈現指數級成長。傳統的人工監控與手動回應機制已無法有效應對每日數以萬計的安全事件,資安團隊面臨著資源有限與威脅無限的嚴峻挑戰。Python 作為一門兼具簡潔語法與強大功能的程式語言,其豐富的生態系統與靈活的擴充性,使其成為現代網路安全自動化的核心工具。透過 Python 的深度整合,資安團隊能夠建立智慧化的威脅偵測系統、自動化的事件回應流程,以及基於機器學習的預測性防禦機制,從根本上提升整體安全防護能力。

Python 在資安自動化領域的技術優勢

Python 在網路安全自動化領域的廣泛應用,源自於其獨特的技術特性與完善的生態系統。相較於其他程式語言,Python 提供了更低的學習曲線與更高的開發效率,使得資安團隊能夠快速實現從概念驗證到生產部署的完整流程。其豐富的第三方套件涵蓋了從網路封包分析、日誌處理、漏洞掃描到機器學習的各個層面,為建構複雜的安全自動化系統提供了堅實的基礎。

在實際的網路安全營運中,Python 腳本能夠無縫整合各種安全工具與平台,實現跨系統的資料串流與自動化處理。透過 Python 的程式化能力,資安人員可以將重複性的日誌分析、事件關聯、威脅情報查詢等工作自動化,大幅降低人力成本的同時,顯著提升回應速度與準確性。這種自動化能力不僅能夠處理已知的安全模式,更能透過機器學習技術識別未知的威脅行為,為組織建立起主動式的防禦體系。

以下是建構 Python 資安自動化系統的核心套件載入與環境設定。這些套件涵蓋了日誌記錄、資料處理、機器學習與視覺化等關鍵功能,為後續的自動化流程奠定技術基礎。

# 核心系統操作套件
import logging  # 提供結構化的日誌記錄功能,用於追蹤系統運作狀態與異常事件
import os  # 處理作業系統層級的檔案與路徑操作
from datetime import datetime  # 處理時間戳記與時間序列資料分析

# 資料科學與分析套件
import pandas as pd  # 高效能的資料框架操作,用於處理結構化資料
import numpy as np  # 數值運算與矩陣操作的基礎套件

# 機器學習與異常偵測
from sklearn.ensemble import IsolationForest  # 基於隔離森林演算法的異常偵測模型
from sklearn.preprocessing import StandardScaler  # 資料標準化處理,確保特徵尺度一致性

# 資料視覺化套件
import matplotlib.pyplot as plt  # 基礎繪圖功能,提供多樣化的圖表類型
import seaborn as sns  # 進階統計視覺化套件,提供更美觀的預設樣式

# 設定日誌記錄系統
logging.basicConfig(
    level=logging.INFO,  # 設定日誌層級為 INFO,記錄一般操作資訊
    format='%(asctime)s - %(levelname)s - %(message)s',  # 定義日誌格式包含時間、層級與訊息
    handlers=[
        logging.FileHandler('security_automation.log'),  # 將日誌寫入檔案供後續分析
        logging.StreamHandler()  # 同時輸出到終端機供即時監控
    ]
)

# 初始化日誌記錄器
logger = logging.getLogger(__name__)
logger.info("Python 資安自動化系統初始化完成")

這段程式碼的架構設計考慮了實際生產環境的需求,透過 logging 模組建立雙重輸出機制,既能在終端機即時顯示運作狀態,又能保存完整的歷史記錄供事後分析。StandardScaler 的引入確保了來自不同來源的資料能夠在統一的尺度下進行比較,這對於機器學習模型的準確性至關重要。Isolation Forest 演算法的選擇則是基於其在高維度資料空間中優異的異常偵測能力,特別適合處理網路流量與使用者行為等複雜資料型態。

機器學習驅動的異常行為偵測實作

在現代網路安全防禦體系中,基於規則的傳統偵測方法已無法有效應對日益複雜的攻擊手法。機器學習技術的引入為威脅偵測帶來了革命性的改變,透過從大量歷史資料中學習正常行為模式,系統能夠自動識別出偏離常態的異常行為,即使這些行為從未出現在既有的威脅情報資料庫中。Isolation Forest 演算法作為一種基於隔離原理的非監督式學習方法,特別適合處理網路安全領域中常見的不平衡資料集問題,因為異常事件通常只佔全部事件的極小比例。

該演算法的核心概念在於,異常資料點由於其特徵與正常資料顯著不同,因此更容易被隔離。演算法透過隨機選擇特徵與分割值來建構決策樹,異常點往往在較少的分割次數後就能被隔離出來,這種特性使得 Isolation Forest 在處理高維度資料時仍能保持良好的效能。在實際應用中,我們可以將網路流量特徵、使用者行為指標、系統日誌資料等轉換為特徵向量,透過模型訓練建立起組織特有的正常行為基準線。

# 設定隨機種子以確保結果可重現性
np.random.seed(42)

# 生成模擬的網路流量特徵資料
# 在實際應用中,這些資料可能來自防火牆日誌、IDS/IPS 系統或 SIEM 平台
data = {
    'packet_size': np.random.normal(1500, 300, 1000),  # 封包大小特徵,模擬正常分布
    'connection_duration': np.random.exponential(5, 1000),  # 連線持續時間,呈指數分布
    'request_frequency': np.random.poisson(10, 1000),  # 請求頻率,符合泊松分布
    'error_rate': np.random.uniform(0, 0.1, 1000)  # 錯誤率,均勻分布於低範圍
}

# 轉換為 Pandas DataFrame 以便於後續處理
df = pd.DataFrame(data)
logger.info(f"載入網路流量資料,共 {len(df)} 筆記錄")

# 資料標準化處理
# StandardScaler 將各特徵轉換為平均值 0、標準差 1 的標準常態分布
scaler = StandardScaler()
scaled_data = scaler.fit_transform(df)
logger.info("完成資料標準化處理")

# 初始化 Isolation Forest 模型
# contamination 參數設定為 0.01,表示預期約 1% 的資料為異常點
# n_estimators 設定決策樹數量,影響模型穩定性與準確度
# random_state 確保訓練過程的可重現性
iso_forest = IsolationForest(
    contamination=0.01,  # 預期異常比例
    n_estimators=100,  # 決策樹數量
    max_samples='auto',  # 自動決定每棵樹的訓練樣本數
    random_state=42,  # 隨機種子
    n_jobs=-1  # 使用所有 CPU 核心加速運算
)

# 訓練模型並進行預測
# 返回值: 1 表示正常資料點, -1 表示異常資料點
predictions = iso_forest.fit_predict(scaled_data)
logger.info(f"異常偵測完成,發現 {sum(predictions == -1)} 筆異常記錄")

# 將預測結果加入原始資料框架
df['anomaly'] = predictions
df['anomaly_label'] = df['anomaly'].map({1: '正常', -1: '異常'})

# 計算異常分數,分數越低表示越異常
anomaly_scores = iso_forest.score_samples(scaled_data)
df['anomaly_score'] = anomaly_scores

# 輸出異常資料的統計資訊
anomalies = df[df['anomaly'] == -1]
if len(anomalies) > 0:
    logger.warning(f"偵測到 {len(anomalies)} 筆異常行為:")
    logger.warning(f"平均封包大小: {anomalies['packet_size'].mean():.2f}")
    logger.warning(f"平均連線時長: {anomalies['connection_duration'].mean():.2f}")
    logger.warning(f"平均請求頻率: {anomalies['request_frequency'].mean():.2f}")

這個實作展示了從資料準備到模型訓練的完整流程,其中每個步驟都經過精心設計以確保在生產環境中的穩定性與可靠性。資料標準化是機器學習前處理的關鍵步驟,因為不同特徵可能具有不同的數值範圍,未經標準化的資料會導致模型偏向數值較大的特徵。Isolation Forest 的 contamination 參數需要根據實際業務環境調整,過高的設定會產生大量誤報,過低則可能遺漏真實的異常事件。

# 建立視覺化分析儀表板
plt.figure(figsize=(15, 10))

# 子圖 1: 封包大小與連線時長的散佈圖
plt.subplot(2, 2, 1)
scatter = plt.scatter(
    df['packet_size'], 
    df['connection_duration'],
    c=df['anomaly'],
    cmap='RdYlGn',  # 使用紅黃綠色階,紅色代表異常
    alpha=0.6,
    s=50
)
plt.xlabel('封包大小 (bytes)', fontsize=12)
plt.ylabel('連線持續時間 (秒)', fontsize=12)
plt.title('網路流量異常偵測視覺化', fontsize=14, fontweight='bold')
plt.colorbar(scatter, label='異常狀態')
plt.grid(True, alpha=0.3)

# 子圖 2: 異常分數分布直方圖
plt.subplot(2, 2, 2)
plt.hist(df['anomaly_score'], bins=50, color='steelblue', alpha=0.7, edgecolor='black')
plt.xlabel('異常分數', fontsize=12)
plt.ylabel('資料點數量', fontsize=12)
plt.title('異常分數分布分析', fontsize=14, fontweight='bold')
plt.axvline(x=df[df['anomaly']==-1]['anomaly_score'].max(), 
            color='red', linestyle='--', label='異常閾值')
plt.legend()
plt.grid(True, alpha=0.3)

# 子圖 3: 請求頻率與錯誤率的關係
plt.subplot(2, 2, 3)
sns.scatterplot(
    data=df,
    x='request_frequency',
    y='error_rate',
    hue='anomaly_label',
    palette={'正常': 'green', '異常': 'red'},
    s=100,
    alpha=0.6
)
plt.xlabel('請求頻率 (次/分鐘)', fontsize=12)
plt.ylabel('錯誤率', fontsize=12)
plt.title('請求模式異常分析', fontsize=14, fontweight='bold')
plt.legend(title='狀態', loc='upper right')
plt.grid(True, alpha=0.3)

# 子圖 4: 特徵重要性分析
plt.subplot(2, 2, 4)
feature_importance = np.abs(df[df['anomaly']==-1].mean() - df[df['anomaly']==1].mean())
features = ['封包大小', '連線時長', '請求頻率', '錯誤率']
plt.barh(features, feature_importance, color='coral', edgecolor='black')
plt.xlabel('特徵差異程度', fontsize=12)
plt.title('異常偵測特徵貢獻度', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, axis='x')

plt.tight_layout()
plt.savefig('/mnt/user-data/outputs/anomaly_detection_visualization.png', dpi=300, bbox_inches='tight')
logger.info("視覺化分析圖表已儲存")
plt.close()

視覺化分析在資安營運中扮演著關鍵角色,它能夠將複雜的統計資料轉換為直觀的圖形,幫助分析師快速識別異常模式與潛在威脅。上述程式碼建立了多維度的視覺化儀表板,從不同角度展示異常偵測的結果,包括特徵空間的分布、異常分數的統計特性,以及各特徵對異常判定的貢獻程度。

@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

start
:收集網路流量資料;
note right
  來源包含:
  * 防火牆日誌
  * IDS/IPS 警報
  * 網路封包擷取
  * 應用程式日誌
end note

:資料前處理與清洗;
note right
  處理步驟:
  * 移除重複記錄
  * 填補缺失值
  * 資料型態轉換
  * 時間序列對齊
end note

:特徵工程與提取;
note right
  關鍵特徵:
  * 流量統計特徵
  * 時間序列特徵
  * 行為模式特徵
  * 協定特徵
end note

:資料標準化處理;
note right
  使用 StandardScaler
  確保特徵尺度一致性
end note

:訓練 Isolation Forest 模型;
note right
  模型參數:
  * contamination: 0.01
  * n_estimators: 100
  * max_samples: auto
end note

:執行異常偵測預測;

if (發現異常資料點?) then (是)
  :計算異常分數;
  :產生告警通知;
  :記錄異常事件;
  note right
    告警內容包含:
    * 異常時間點
    * 相關特徵值
    * 異常嚴重程度
    * 建議處置措施
  end note
else (否)
  :更新正常行為基準;
endif

:視覺化分析結果;
note right
  產出內容:
  * 異常分布圖
  * 時間序列圖
  * 特徵相關性圖
  * 統計報表
end note

:儲存模型與分析結果;

stop
@enduml

這個流程圖完整呈現了機器學習驅動的異常偵測系統的運作邏輯,從資料收集到最終的告警產生,每個環節都經過精心設計以確保系統的準確性與可靠性。在實際部署時,這個流程可以整合到 SIEM 平台或 SOC 系統中,實現即時的威脅偵測與自動化回應。

企業級使用者行為分析系統架構

使用者與實體行為分析已成為現代資安防護體系中不可或缺的一環,透過持續監控與分析使用者的日常操作行為,系統能夠建立個人化的行為基準線,進而識別出帳號被盜用、內部威脅或異常存取等安全事件。UEBA 系統整合了機器學習、統計分析與威脅情報,提供更精確的風險評估與預測能力。在台灣的企業環境中,考慮到個人資料保護法的規範,UEBA 系統的設計必須在安全監控與隱私保護之間取得適當平衡。

實作一個完整的 UEBA 系統需要整合多個資料來源,包括身份認證系統、檔案伺服器存取記錄、電子郵件系統、網路流量分析等。透過 Python 的強大整合能力,我們可以建立一個統一的資料處理管道,將來自不同系統的資料標準化後進行綜合分析。以下是一個簡化的 UEBA 系統核心元件實作。

import json
from collections import defaultdict
from datetime import datetime, timedelta

class UserBehaviorAnalyzer:
    """
    使用者行為分析器
    用於監控與分析使用者的操作行為模式,偵測異常活動
    """
    
    def __init__(self):
        """初始化行為分析器,建立使用者行為基準資料結構"""
        self.user_baselines = defaultdict(lambda: {
            'login_times': [],  # 登入時間記錄
            'access_locations': [],  # 存取地點記錄
            'file_operations': [],  # 檔案操作記錄
            'data_transfer_volume': [],  # 資料傳輸量記錄
            'failed_login_attempts': 0,  # 登入失敗次數
            'privilege_escalations': 0  # 權限提升次數
        })
        logger.info("使用者行為分析器初始化完成")
    
    def update_baseline(self, user_id, activity_type, activity_data):
        """
        更新使用者行為基準線
        
        參數:
            user_id: 使用者識別碼
            activity_type: 活動類型
            activity_data: 活動資料
        """
        if activity_type == 'login':
            login_time = datetime.fromisoformat(activity_data['timestamp'])
            self.user_baselines[user_id]['login_times'].append(login_time.hour)
            self.user_baselines[user_id]['access_locations'].append(activity_data['location'])
            
        elif activity_type == 'file_access':
            self.user_baselines[user_id]['file_operations'].append({
                'timestamp': activity_data['timestamp'],
                'file_path': activity_data['file_path'],
                'operation': activity_data['operation']
            })
            
        elif activity_type == 'data_transfer':
            self.user_baselines[user_id]['data_transfer_volume'].append(
                activity_data['volume_mb']
            )
        
        logger.debug(f"更新使用者 {user_id}{activity_type} 行為基準")
    
    def detect_anomalies(self, user_id, current_activity):
        """
        偵測使用者當前活動是否異常
        
        參數:
            user_id: 使用者識別碼
            current_activity: 當前活動資料
            
        返回:
            異常偵測結果與風險分數
        """
        baseline = self.user_baselines[user_id]
        anomalies = []
        risk_score = 0
        
        # 偵測異常登入時間
        if current_activity['type'] == 'login':
            login_hour = datetime.fromisoformat(current_activity['timestamp']).hour
            typical_hours = set(baseline['login_times'])
            
            if typical_hours and login_hour not in typical_hours:
                anomalies.append({
                    'type': '異常登入時間',
                    'details': f'使用者通常不在 {login_hour}:00 登入',
                    'severity': 'medium'
                })
                risk_score += 30
        
        # 偵測異常存取地點
        if current_activity.get('location'):
            if baseline['access_locations']:
                common_locations = set(baseline['access_locations'])
                if current_activity['location'] not in common_locations:
                    anomalies.append({
                        'type': '異常存取地點',
                        'details': f'從未知地點 {current_activity["location"]} 存取',
                        'severity': 'high'
                    })
                    risk_score += 50
        
        # 偵測異常資料傳輸量
        if current_activity['type'] == 'data_transfer':
            if baseline['data_transfer_volume']:
                avg_volume = np.mean(baseline['data_transfer_volume'])
                std_volume = np.std(baseline['data_transfer_volume'])
                current_volume = current_activity['volume_mb']
                
                # 使用統計方法判定異常(超過平均值 3 個標準差)
                if current_volume > avg_volume + 3 * std_volume:
                    anomalies.append({
                        'type': '異常資料傳輸量',
                        'details': f'傳輸量 {current_volume}MB 遠超過平均值 {avg_volume:.2f}MB',
                        'severity': 'critical'
                    })
                    risk_score += 70
        
        # 產生綜合風險評估
        if anomalies:
            logger.warning(f"使用者 {user_id} 偵測到 {len(anomalies)} 項異常行為,總風險分數: {risk_score}")
            return {
                'is_anomalous': True,
                'anomalies': anomalies,
                'risk_score': risk_score,
                'risk_level': self._calculate_risk_level(risk_score),
                'timestamp': datetime.now().isoformat()
            }
        
        return {'is_anomalous': False, 'risk_score': 0}
    
    def _calculate_risk_level(self, risk_score):
        """根據風險分數計算風險等級"""
        if risk_score >= 70:
            return 'critical'
        elif risk_score >= 50:
            return 'high'
        elif risk_score >= 30:
            return 'medium'
        else:
            return 'low'
    
    def generate_user_report(self, user_id):
        """
        產生使用者行為分析報告
        
        參數:
            user_id: 使用者識別碼
            
        返回:
            詳細的使用者行為分析報告
        """
        baseline = self.user_baselines[user_id]
        
        report = {
            'user_id': user_id,
            'report_generated': datetime.now().isoformat(),
            'statistics': {
                'total_logins': len(baseline['login_times']),
                'common_login_hours': self._get_common_hours(baseline['login_times']),
                'access_locations': list(set(baseline['access_locations'])),
                'total_file_operations': len(baseline['file_operations']),
                'avg_data_transfer_mb': np.mean(baseline['data_transfer_volume']) if baseline['data_transfer_volume'] else 0,
                'failed_login_attempts': baseline['failed_login_attempts'],
                'privilege_escalations': baseline['privilege_escalations']
            },
            'behavioral_insights': self._generate_insights(baseline)
        }
        
        logger.info(f"已產生使用者 {user_id} 的行為分析報告")
        return report
    
    def _get_common_hours(self, login_times):
        """分析最常見的登入時段"""
        if not login_times:
            return []
        hour_counts = {}
        for hour in login_times:
            hour_counts[hour] = hour_counts.get(hour, 0) + 1
        # 返回出現次數最多的前三個時段
        return sorted(hour_counts.items(), key=lambda x: x[1], reverse=True)[:3]
    
    def _generate_insights(self, baseline):
        """產生行為洞察建議"""
        insights = []
        
        # 分析登入模式
        if baseline['login_times']:
            unique_hours = len(set(baseline['login_times']))
            if unique_hours <= 3:
                insights.append("使用者具有固定的登入時間模式,適合設定時間基準告警")
        
        # 分析資料傳輸行為
        if baseline['data_transfer_volume']:
            avg_volume = np.mean(baseline['data_transfer_volume'])
            if avg_volume > 1000:  # 超過 1GB
                insights.append("使用者經常進行大量資料傳輸,建議加強資料外洩防護監控")
        
        # 分析存取地點
        if len(set(baseline['access_locations'])) > 5:
            insights.append("使用者從多個不同地點存取系統,可能為遠端工作者或差旅人員")
        
        return insights

# 使用範例
analyzer = UserBehaviorAnalyzer()

# 模擬使用者行為資料建立基準線
for i in range(30):  # 模擬 30 天的正常行為
    analyzer.update_baseline('user001', 'login', {
        'timestamp': (datetime.now() - timedelta(days=i)).replace(hour=9).isoformat(),
        'location': 'Taipei_Office'
    })
    
    analyzer.update_baseline('user001', 'data_transfer', {
        'timestamp': (datetime.now() - timedelta(days=i)).isoformat(),
        'volume_mb': np.random.normal(100, 20)  # 平均 100MB,標準差 20MB
    })

# 偵測異常活動
anomaly_result = analyzer.detect_anomalies('user001', {
    'type': 'login',
    'timestamp': datetime.now().replace(hour=3).isoformat(),  # 凌晨 3 點登入
    'location': 'Unknown_Location'  # 未知地點
})

print(json.dumps(anomaly_result, indent=2, ensure_ascii=False))

# 產生使用者行為報告
user_report = analyzer.generate_user_report('user001')
print(json.dumps(user_report, indent=2, ensure_ascii=False))

這個 UEBA 系統的實作展示了如何透過物件導向設計建立可擴充的行為分析框架,其中包含了基準線建立、異常偵測、風險評分與報告產生等核心功能。在實際應用中,這個系統可以進一步整合身份認證系統、存取控制系統與 SIEM 平台,實現全方位的使用者行為監控。

自動化事件回應與威脅獵捕平台

當資安事件發生時,回應速度往往決定了損害的程度。傳統的人工事件回應流程通常需要數小時甚至數天的時間來完成調查、分析與處置,這段時間足以讓攻擊者完成資料竊取或橫向移動。透過 Python 建構的自動化事件回應平台,能夠在偵測到威脅的第一時間自動執行預定義的回應措施,包括帳號隔離、網路封鎖、系統快照、證據收集等,大幅縮短從偵測到回應的時間差。

Security Orchestration Automation and Response 技術整合了多個安全工具與流程,透過劇本的方式定義標準化的回應程序。當特定類型的安全事件發生時,SOAR 平台能夠自動觸發相對應的劇本,執行一系列預定義的動作,同時保持完整的操作記錄供稽核使用。以下展示一個簡化的 SOAR 系統核心元件實作。

from enum import Enum
from typing import List, Dict, Callable
import time

class ThreatSeverity(Enum):
    """威脅嚴重程度分級"""
    CRITICAL = 4  # 重大威脅,需要立即回應
    HIGH = 3  # 高風險威脅
    MEDIUM = 2  # 中等風險威脅
    LOW = 1  # 低風險威脅

class IncidentStatus(Enum):
    """事件處理狀態"""
    DETECTED = "detected"  # 已偵測
    INVESTIGATING = "investigating"  # 調查中
    CONTAINED = "contained"  # 已隔離
    REMEDIATED = "remediated"  # 已修復
    CLOSED = "closed"  # 已結案

class SecurityIncident:
    """資安事件物件,記錄事件的完整生命週期"""
    
    def __init__(self, incident_id, incident_type, severity, source, description):
        self.incident_id = incident_id
        self.incident_type = incident_type
        self.severity = severity
        self.source = source
        self.description = description
        self.status = IncidentStatus.DETECTED
        self.detected_time = datetime.now()
        self.actions_taken = []  # 記錄所有執行的回應動作
        self.indicators = {}  # 儲存相關的威脅指標
        
    def add_action(self, action_name, action_result):
        """記錄執行的回應動作"""
        self.actions_taken.append({
            'action': action_name,
            'result': action_result,
            'timestamp': datetime.now().isoformat()
        })
        logger.info(f"事件 {self.incident_id} 執行動作: {action_name}")
    
    def update_status(self, new_status):
        """更新事件處理狀態"""
        old_status = self.status
        self.status = new_status
        logger.info(f"事件 {self.incident_id} 狀態變更: {old_status.value} -> {new_status.value}")

class SOARPlaybook:
    """SOAR 劇本,定義自動化回應流程"""
    
    def __init__(self, playbook_name, trigger_conditions, actions):
        self.playbook_name = playbook_name
        self.trigger_conditions = trigger_conditions  # 觸發條件
        self.actions = actions  # 要執行的動作序列
        self.execution_count = 0  # 執行次數統計
        
    def should_trigger(self, incident: SecurityIncident) -> bool:
        """判斷是否應該觸發此劇本"""
        for condition_key, condition_value in self.trigger_conditions.items():
            if condition_key == 'incident_type':
                if incident.incident_type not in condition_value:
                    return False
            elif condition_key == 'min_severity':
                if incident.severity.value < condition_value.value:
                    return False
        return True
    
    def execute(self, incident: SecurityIncident, context: Dict) -> bool:
        """執行劇本定義的所有動作"""
        logger.info(f"開始執行劇本: {self.playbook_name} (事件: {incident.incident_id})")
        incident.update_status(IncidentStatus.INVESTIGATING)
        
        for action in self.actions:
            try:
                # 執行動作並記錄結果
                result = action['function'](incident, context)
                incident.add_action(action['name'], result)
                
                # 如果動作執行失敗且標記為必要動作,則停止劇本執行
                if not result['success'] and action.get('required', False):
                    logger.error(f"必要動作 {action['name']} 執行失敗,中止劇本")
                    return False
                    
                # 動作間的等待時間,避免系統過載
                time.sleep(action.get('wait_seconds', 1))
                
            except Exception as e:
                logger.error(f"執行動作 {action['name']} 時發生錯誤: {str(e)}")
                incident.add_action(action['name'], {
                    'success': False,
                    'error': str(e)
                })
                if action.get('required', False):
                    return False
        
        self.execution_count += 1
        logger.info(f"劇本 {self.playbook_name} 執行完成")
        return True

class SOAROrchestrator:
    """SOAR 協調器,管理所有劇本與事件回應流程"""
    
    def __init__(self):
        self.playbooks = []  # 儲存所有劇本
        self.incidents = []  # 儲存所有事件
        self.response_actions = self._initialize_actions()  # 初始化回應動作函式庫
        logger.info("SOAR 協調器初始化完成")
    
    def _initialize_actions(self) -> Dict[str, Callable]:
        """初始化所有可用的回應動作"""
        return {
            'isolate_host': self._isolate_host,
            'block_ip': self._block_ip,
            'disable_account': self._disable_account,
            'collect_forensics': self._collect_forensics,
            'send_alert': self._send_alert,
            'create_ticket': self._create_ticket,
            'quarantine_file': self._quarantine_file
        }
    
    def register_playbook(self, playbook: SOARPlaybook):
        """註冊新的 SOAR 劇本"""
        self.playbooks.append(playbook)
        logger.info(f"註冊劇本: {playbook.playbook_name}")
    
    def handle_incident(self, incident: SecurityIncident, context: Dict = None):
        """
        處理資安事件,自動執行相符的劇本
        
        參數:
            incident: 資安事件物件
            context: 額外的上下文資訊
        """
        if context is None:
            context = {}
        
        self.incidents.append(incident)
        logger.warning(f"收到新事件: {incident.incident_id} - {incident.description}")
        
        # 尋找符合觸發條件的劇本
        triggered_playbooks = [
            playbook for playbook in self.playbooks 
            if playbook.should_trigger(incident)
        ]
        
        if not triggered_playbooks:
            logger.warning(f"事件 {incident.incident_id} 沒有符合的劇本")
            return
        
        # 執行所有觸發的劇本
        for playbook in triggered_playbooks:
            success = playbook.execute(incident, context)
            if success:
                incident.update_status(IncidentStatus.CONTAINED)
            else:
                logger.error(f"劇本 {playbook.playbook_name} 執行失敗")
        
        # 根據嚴重程度決定後續動作
        if incident.severity == ThreatSeverity.CRITICAL:
            incident.update_status(IncidentStatus.REMEDIATED)
            self._escalate_to_team(incident)
    
    # 以下是各種回應動作的實作
    def _isolate_host(self, incident: SecurityIncident, context: Dict) -> Dict:
        """隔離受感染的主機"""
        host_id = context.get('host_id', 'unknown')
        logger.warning(f"執行主機隔離: {host_id}")
        # 實際環境中,這裡會呼叫網路管理 API 或 EDR 平台 API
        return {
            'success': True,
            'message': f'主機 {host_id} 已從網路隔離',
            'isolated_at': datetime.now().isoformat()
        }
    
    def _block_ip(self, incident: SecurityIncident, context: Dict) -> Dict:
        """封鎖惡意 IP 位址"""
        ip_address = context.get('ip_address', 'unknown')
        logger.warning(f"執行 IP 封鎖: {ip_address}")
        # 實際環境中,這裡會更新防火牆規則或呼叫 IPS API
        return {
            'success': True,
            'message': f'IP 位址 {ip_address} 已加入黑名單',
            'blocked_at': datetime.now().isoformat()
        }
    
    def _disable_account(self, incident: SecurityIncident, context: Dict) -> Dict:
        """停用受侵害的帳號"""
        user_id = context.get('user_id', 'unknown')
        logger.warning(f"執行帳號停用: {user_id}")
        # 實際環境中,這裡會呼叫 Active Directory 或 IAM 系統 API
        return {
            'success': True,
            'message': f'使用者帳號 {user_id} 已停用',
            'disabled_at': datetime.now().isoformat()
        }
    
    def _collect_forensics(self, incident: SecurityIncident, context: Dict) -> Dict:
        """收集數位鑑識證據"""
        host_id = context.get('host_id', 'unknown')
        logger.info(f"執行證據收集: {host_id}")
        # 實際環境中,這裡會觸發記憶體映像、磁碟快照等鑑識工具
        return {
            'success': True,
            'message': f'已收集主機 {host_id} 的鑑識證據',
            'evidence_location': f'/forensics/{incident.incident_id}/{host_id}',
            'collected_at': datetime.now().isoformat()
        }
    
    def _send_alert(self, incident: SecurityIncident, context: Dict) -> Dict:
        """發送告警通知"""
        recipients = context.get('recipients', ['soc@example.com'])
        logger.info(f"發送告警通知給: {', '.join(recipients)}")
        # 實際環境中,這裡會整合郵件系統、簡訊閘道或通訊軟體 API
        return {
            'success': True,
            'message': f'告警已發送給 {len(recipients)} 位收件者',
            'sent_at': datetime.now().isoformat()
        }
    
    def _create_ticket(self, incident: SecurityIncident, context: Dict) -> Dict:
        """建立事件追蹤單"""
        logger.info(f"建立事件追蹤單: {incident.incident_id}")
        # 實際環境中,這裡會整合 ITSM 系統如 ServiceNow、Jira 等
        return {
            'success': True,
            'ticket_id': f'INC-{incident.incident_id}',
            'message': '事件追蹤單已建立',
            'created_at': datetime.now().isoformat()
        }
    
    def _quarantine_file(self, incident: SecurityIncident, context: Dict) -> Dict:
        """隔離惡意檔案"""
        file_path = context.get('file_path', 'unknown')
        file_hash = context.get('file_hash', 'unknown')
        logger.warning(f"執行檔案隔離: {file_path}")
        # 實際環境中,這裡會呼叫防毒軟體或 EDR 平台 API
        return {
            'success': True,
            'message': f'檔案已隔離',
            'file_path': file_path,
            'file_hash': file_hash,
            'quarantined_at': datetime.now().isoformat()
        }
    
    def _escalate_to_team(self, incident: SecurityIncident):
        """將重大事件升級至資安團隊處理"""
        logger.critical(f"重大事件升級: {incident.incident_id}")
        # 實際環境中,這裡會觸發緊急通知流程
    
    def generate_incident_report(self, incident_id: str) -> Dict:
        """產生事件處理報告"""
        incident = next((inc for inc in self.incidents if inc.incident_id == incident_id), None)
        
        if not incident:
            return {'error': '事件不存在'}
        
        return {
            'incident_id': incident.incident_id,
            'incident_type': incident.incident_type,
            'severity': incident.severity.name,
            'status': incident.status.value,
            'detected_time': incident.detected_time.isoformat(),
            'description': incident.description,
            'actions_taken': incident.actions_taken,
            'total_actions': len(incident.actions_taken),
            'response_time_seconds': (
                datetime.now() - incident.detected_time
            ).total_seconds() if incident.status != IncidentStatus.CLOSED else None
        }

# 使用範例
orchestrator = SOAROrchestrator()

# 定義惡意軟體回應劇本
malware_playbook = SOARPlaybook(
    playbook_name="惡意軟體標準回應流程",
    trigger_conditions={
        'incident_type': ['malware', 'ransomware'],
        'min_severity': ThreatSeverity.MEDIUM
    },
    actions=[
        {
            'name': '隔離受感染主機',
            'function': orchestrator.response_actions['isolate_host'],
            'required': True
        },
        {
            'name': '收集鑑識證據',
            'function': orchestrator.response_actions['collect_forensics'],
            'required': True
        },
        {
            'name': '隔離惡意檔案',
            'function': orchestrator.response_actions['quarantine_file'],
            'required': True
        },
        {
            'name': '發送告警通知',
            'function': orchestrator.response_actions['send_alert'],
            'required': False
        },
        {
            'name': '建立事件追蹤單',
            'function': orchestrator.response_actions['create_ticket'],
            'required': False
        }
    ]
)

# 定義帳號入侵回應劇本
account_compromise_playbook = SOARPlaybook(
    playbook_name="帳號入侵回應流程",
    trigger_conditions={
        'incident_type': ['account_compromise', 'credential_theft'],
        'min_severity': ThreatSeverity.HIGH
    },
    actions=[
        {
            'name': '停用受侵害帳號',
            'function': orchestrator.response_actions['disable_account'],
            'required': True
        },
        {
            'name': '封鎖可疑 IP',
            'function': orchestrator.response_actions['block_ip'],
            'required': True
        },
        {
            'name': '發送緊急告警',
            'function': orchestrator.response_actions['send_alert'],
            'required': True
        },
        {
            'name': '建立事件追蹤單',
            'function': orchestrator.response_actions['create_ticket'],
            'required': False
        }
    ]
)

# 註冊劇本
orchestrator.register_playbook(malware_playbook)
orchestrator.register_playbook(account_compromise_playbook)

# 模擬惡意軟體事件
malware_incident = SecurityIncident(
    incident_id="INC-2025-001",
    incident_type="ransomware",
    severity=ThreatSeverity.CRITICAL,
    source="EDR_System",
    description="偵測到勒索軟體活動於主機 WS-001"
)

# 處理事件
orchestrator.handle_incident(malware_incident, context={
    'host_id': 'WS-001',
    'file_path': 'C:\\Users\\user\\Desktop\\malware.exe',
    'file_hash': 'a1b2c3d4e5f6',
    'recipients': ['soc@example.com', 'incident-response@example.com']
})

# 產生事件報告
report = orchestrator.generate_incident_report("INC-2025-001")
print(json.dumps(report, indent=2, ensure_ascii=False))

這個 SOAR 系統的實作展示了如何透過物件導向設計建立可擴充的自動化回應框架,支援劇本管理、事件追蹤與多層級的回應動作。在實際部署時,這個系統可以整合企業現有的安全工具,如 SIEM、EDR、防火牆、IPS 等,實現真正的自動化協調回應。

@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

|安全監控系統|
start
:偵測到可疑活動;
note right
  觸發來源:
  * SIEM 告警
  * IDS/IPS 警報
  * EDR 端點偵測
  * 異常行為分析
end note

|SOAR 協調器|
:接收事件通知;
:建立事件物件;

:尋找符合的劇本;
note right
  評估條件:
  * 事件類型比對
  * 嚴重程度評估
  * 資產重要性
  * 觸發條件邏輯
end note

if (找到符合劇本?) then (是)
  :載入劇本設定;
  :更新事件狀態為調查中;
  
  |劇本執行引擎|
  repeat
    :執行劇本動作;
    
    fork
      :主機隔離;
    fork again
      :IP 封鎖;
    fork again
      :帳號停用;
    fork again
      :證據收集;
    fork again
      :告警通知;
    end fork
    
    :記錄執行結果;
    
    if (動作執行成功?) then (是)
      :繼續下一動作;
    else (否)
      if (是必要動作?) then (是)
        :中止劇本執行;
        :記錄失敗原因;
        stop
      else (否)
        :記錄警告訊息;
      endif
    endif
    
  repeat while (還有待執行動作?) is (是)
  ->否;
  
  |SOAR 協調器|
  :更新事件狀態為已隔離;
  
  if (嚴重程度為重大?) then (是)
    :升級至資安團隊;
    :發送緊急通知;
    note right
      通知管道:
      * 電子郵件
      * 簡訊
      * 通訊軟體
      * 值班電話
    end note
  endif
  
else (否)
  :記錄無符合劇本;
  :建立人工處理工單;
endif

|事件追蹤系統|
:建立事件追蹤單;
:更新 ITSM 系統;

|報告產生器|
:收集所有執行記錄;
:產生事件處理報告;
note right
  報告內容:
  * 事件時間軸
  * 執行動作清單
  * 回應時間統計
  * 改善建議
end note

:歸檔事件資料;

stop
@enduml

這個流程圖完整呈現了 SOAR 系統的自動化事件回應流程,從威脅偵測到最終的報告產生,每個環節都經過精心設計以確保快速有效的回應能力。在實際運作中,這個系統能夠在數秒到數分鐘內完成原本需要數小時的人工處理流程。

持續學習文化與跨部門協作實踐

在網路安全領域,技術的演進速度與威脅的變化態勢要求資安團隊必須建立持續學習的文化機制。僅僅依賴既有知識與過往經驗已無法有效應對不斷湧現的新型攻擊手法,資安專業人員需要透過系統化的學習路徑,持續更新技術能力與威脅認知。這包括定期參與國際資安會議、取得專業認證、進行實戰演練,以及透過威脅情報社群掌握最新的攻擊趨勢。

跨部門協作是強化組織整體安全態勢的關鍵因素,資安不再只是資安部門的責任,而是需要開發團隊、IT 營運團隊、法務合規單位、業務部門等共同參與的全組織性工作。透過建立 DevSecOps 文化,將安全要求從開發階段就深度整合,能夠在源頭降低安全風險。定期舉辦跨部門的資安演練,模擬真實的攻擊場景與事件回應流程,有助於提升團隊間的協調效率與溝通品質。

建立有效的威脅情報分享機制同樣重要,透過參與產業資安情報分享平台,如台灣電腦網路危機處理暨協調中心提供的情報交換機制,組織能夠及時掌握針對特定產業或地區的威脅活動。內部建立威脅情報管理系統,整合來自不同來源的情報資料,透過自動化分析與關聯,提供可操作的情報洞察,協助資安團隊做出更明智的防護決策。

雲端與新興技術環境的安全挑戰

隨著企業數位轉型的深化,雲端運算與物聯網設備的廣泛採用為資安防護帶來新的挑戰維度。傳統的網路邊界防禦模式在雲端環境中已不再適用,取而代之的是零信任架構的安全理念,要求對每一次存取請求都進行身份驗證與授權檢查,不再僅依賴網路位置作為信任基礎。Python 在雲端安全自動化中扮演重要角色,透過雲端服務商提供的 SDK 與 API,資安團隊能夠實現雲端資源的自動化監控、合規檢查與安全配置管理。

物聯網設備的安全防護面臨著資源受限、更新困難、協定多樣等獨特挑戰,需要從設備端到雲端建立完整的安全防護鏈路。透過 Python 開發的物聯網安全監控系統,能夠即時分析設備間的通訊行為,識別異常的資料傳輸模式,並在偵測到可疑活動時自動隔離受影響的設備,防止威脅在物聯網網路中擴散。

結語

Python 在網路安全自動化領域的應用已從簡單的腳本工具演進為企業級的智慧防護系統,其豐富的生態系統與強大的整合能力,使其成為現代資安團隊不可或缺的技術基石。透過本文介紹的機器學習異常偵測、使用者行為分析、自動化事件回應等技術實踐,資安團隊能夠建立起更主動、更智慧的防禦體系,有效應對日益複雜的威脅挑戰。

未來的網路安全防護將更加依賴人工智慧與自動化技術的深度整合,從被動防禦轉向主動獵捕,從規則驅動轉向智慧決策。資安團隊需要持續投資於技術能力的提升,建立跨部門的協作機制,培養適應變化的組織文化,方能在數位時代的安全競賽中保持領先地位。Python 作為連結理論與實踐的橋樑,將繼續在這個演進過程中發揮關鍵作用,為組織的數位安全保駕護航。