從海量安全事件中挖掘有用的威脅信息與情報是當今討論的熱門話題,同時這也是一個難點?怎麼實現呢?這裏用到一種技術叫作關聯分析,他也是SIEM(Security Information Event Management安全信息和事件管理)系統中最多見的事件檢測手段,這並非什麼新鮮事物,20年前就已經有人提出來了。一般基於時序來對相同數據源或來自不一樣數據源的安全事件,使用關聯規則來進行綜合的關聯分析,下面介紹關聯分析的具體功能。node
一般來講,一次惡意Gong JI會在多個安全設備或應用程序(如網絡防火牆,交換機,Web 應用日誌,SQL 日誌,審覈日誌等)中留下痕跡. 然而,全部這些信息都是孤立隔絕的,被保存在不一樣的設備日誌中,若是利用了關聯分析技術就能夠快速定位故障。
關聯分析爲何有如此神通廣大呢?其實後臺有不少複雜的關聯規則最爲基礎的,這些檢測規則能夠識別 A t t a c k 事件,實際上這些規則是人工在大量實踐中總結出來生成對Gong JI事件的一種語言描述,並對其進行了精確分類,分類越細描述越準確,識別率就越高。算法
Tips: 下文中「Gong Ji」「**」表明銘感詞彙,你懂得。數據庫
1、關聯分析核心思想安全
關聯分析技術的核心思想是經過對某一類事件進行訓練創建行爲基線,基線範圍外的事件視爲異常事件來進行分類. 該算法較適合於本文檢測場景,一般 SIEM 系統中絕大多數的日誌爲正常事件,經過對正常事件訓練建模,來檢測異常或Gong JI事件,這就是理論上說的One-Class SVM(單類支持向量機)。OSSIM系統中須要更多維度特徵向量,才能準確判斷Gong JI源,避免檢測精度低或過擬合狀況. 算法輸入是通過 OSSIM 歸一化後具有相同數據結構的安全事件,輸出則爲帶有標記的安全事件,標記分爲兩類:正常(Negative)與Gong JI(Positive). 而OSSIM關聯分析引擎的輸出就是 One-Class SVM分類算法輸出的帶標記的正常與Gong JI事件。服務器
經過深刻分析 SIEM 系統的關聯規則,其中最多見的配置字段如:event_id,timestamp,plugin_id,plugin_sid,src_ip,src_port,des_ip,des_port,protocol 等。 爲了使關聯分析規則不依賴於傳感器配置,本文從 OSSIM 的規則庫中抽取了幾個重要的字段 plugin_id_name,plu-gin_id_description,sid_name,並將全部字段拆分紅關鍵詞標籤,而後針對每一條檢測規則生成其關鍵詞標籤統計模型,利用規則統計模型來代替原始的規則來檢測Gong JI。網絡
關聯分析的核心經過一個或一組關聯指令來完成,下面用SSH破解的例子加以說明,如圖1所示,SSH破解(Brute Force)大約自UNIX誕生以後,就衍生出來的一種Gong JI行爲,據統計發現大約有50%以上的用戶名是root。一個低可靠性(low reliability)的SSH 服務器,在通過100登陸嘗試以後成功登陸,而高可靠性(high reliability)的SSH服務器,則通過10000次登陸才成功,那麼關聯引擎可經過在必定時間內,登陸的次數,以及這些時間的不一樣源地址和相同目標IP地址,以及這些IP地址來自於那些國家,它們信譽度如何等信息來綜合斷定Gong JI以及做出響應。數據結構
image.png運維
圖1ssh
下面你們將親生經歷關聯引擎的關聯指令的組成結構。函數
2、 關聯指令配置界面
OSSIM中關聯指令的界面經過Configuration->Threat Intelligence->Directives打開,通過前面幾節的內容的學習,你們或多或少的已經接觸過關聯指令的界面,下面咱們進行一下概括,以下圖2所示。
image.png
圖2 OSSIM 關聯指令界面
關鍵功能解釋:
New Directive:單擊此選項以從頭開始建立一個新的指令。
Test Directives:單擊此按鈕,將檢測當前新建/修改的指令是否正確。
Restart Server:單擊此按鈕,將重啓ossim-server進程,凡是修改了任何一條關聯指令都需從新啓動Server,按這個按鈕比你重啓整個USM服務器更明智。
須要注意的是,雖然重啓時間短暫,但重啓期間全部關聯數據會丟失。
image.png
圖3 一條完整指令
● Sensor:傳感器,用於收集各類事件信息。
● Protocol:協議,包括ANY、TCP、UDP、ICMP。
● Sticky different:
還記得Linux基礎是指中,用於文件及目錄屬性設定的sticky位嗎?從OSSIM 4.3起在關聯指令中添加了新屬性,Sticky different(不一樣的粘粘位)域,規則中Sticky different爲None。它是用來設定指令規則的屬性,
有關Sticky different的取值你們可參考/etc/ossim/server/directives.xsd文件
<xs:simpleType name="stickydifferenttype">
... ...略
</xs:simpleType>
當新收集的事件到達關聯引擎時,它將和已有的事件相關聯,若是事件屬性(如IP地址和端口號)相同,但一個指令的屬性裏能夠設置不一樣的粘粘位,好比None、DST_PORT、SRC_IP、PLUGIN_ID等,用來區別收到的不一樣事件,以便進行相互關聯。例如在端口掃描類Gong JI中,若是你設置目標端口爲Sticky different,那麼只有來自不一樣目標端口的事件被關聯。
3、在OSSIM 的Web UI中查看效果
下面咱們查看實際的例子,如圖4所示。
image.png
圖4 STICKY DIFF
打開/etc/ossim/server/alienvault-dos.xml查看關聯指令AvAttacks,Possible DDOS spacer.gif
image.png
● Username:事件中指定的用戶名
● Pass: 事件中指定的口令
● Userdata1~Userdata8:事件中指定的數據域。
image.png
圖5 查看更對關聯規則屬性
注意,From、To、Data source 、Event Type 列下方的spacer.gif號表示可修改,Action下的spacer.gif號表明可添加規則 ,但系統默認指令中的規則不容許修改。
4、深刻關聯規則
在OSSIM利用預先定義的規則(/etc/ossim/server/*.xml)來進行關聯分析。那麼咱們如何操做呢,首先,咱們經過Web界面,新建一個Correlation Directives,新建兩個規則ssh和test,而後咱們看看詳細文件內容,路徑在/etc/ossim/server目錄,名爲user.xml文件。其餘默認規則由/etc/ossim/server/directives.xml定義,如圖6所示。
image.png
圖6 自定義指令
當系統調用Directive下的策略是,首先根據categories.xml配置文件讀取相應的XML配置文件,這些文件功能以下:
策略文件存儲位置:/etc/ossim/server/及說明
Ø alienvault-attacks.xml AlienVault Gong JI類策略
Ø alienvault-bruteforce.xml AlienVault**破解類Gong JI
Ø alienvault-dos.xml Alienvault拒絕服務類
Ø alienvault-malware.xml Alienvault 惡意軟件(包括檢測各類蠕蟲的規則)
Ø alienvault-misc.xml Alienvault各類失誤類(Miscellaneous)
Ø alienvault-network.xml Alienvault網絡類 (開源版無此項)
Ø alienvault-policy.xml Alienvault策略
Ø alienvault-scan.xml Alienvault掃描
Ø user.xml Alienvault用戶自定義
若是OSSIM關聯引擎讀不到這些策略配置文件,在Analysis→Alarm就不會生成報警。接下來咱們詳細看看一個xml的例子。
2.理解規則樹
關聯引擎經過規則來實現對安全事件的關聯分析,讀者須要可以看懂OSSIM的規則,其中採用了特有的樹形規則,在規則樹中的每個節點對應一條關聯規則(rules)。在匹配時關聯引擎將某段時間內收到的統一格式的報警,從根節點開始往葉子節點逐次匹配,系統根據匹配的結果能夠進行事件聚合和再次提高報警級別。下面看個實例:
image.png
圖7 自定義指令內容
從上圖能夠看出,這種基於事件序列的關聯方法中的每條指令至關於一顆由規則組成的樹,因此能夠把它叫作基於樹形指令(Directive)的關聯方法,其基本思想是根據相關事件序列建立一系列的規則來表示Gong JI場景,在OSSIM系統中採用了XML來定義關聯序列,關聯分析引擎啓動時就將全部關聯導入每一個關聯規則序列由下面標籤組成將上面的實際xml提煉一下,獲得以下模板:
<directive id="" name="" priority="">
<rule type="" name="" reliability="" occurence="」 from="" to="" port_from="" port_to="" plugin_id=""plugin_sid="">
<rules>
<rules>
......
</rules
......
</rule>
</directive>
每一個序列開頭包括兩個標籤「directive_id」和「directive name」,而每一個序列,又包括不少規則,規則之中又能夠嵌套規則,即遞歸方法。
其中Rule 表明規則,規則後面表明一個可能發生的Gong JI場景,Event 表明在當前已發生的Gong JI場景下,一個Gong JI場景由若干條規則組成,這些規則多是「與」和「或」的關係。這樣表示的好處是,咱們清楚的知道,若是一個Gong JI場景發生,那麼只須要知足哪些規則便可。
經過計算每一個Rule 裏的Reliability 來確認這個Gong JI發生的可信度是多少。其中Scene 的id用directive_id來表示;前面講過Reliability 能夠是0~10之間的數,直接給可靠性賦值,也可使一個修改量,表示當這個規則知足時將前一步Gong JI場景的可靠性作修改,將結果存入New_Reliability中;規則部分的其它屬性表明了將和它作匹配的Event 的屬性值;而和數據庫的具體交互是經過Action 來表示。
下面咱們看個實際的例子,下面這段指令主要是用來檢測公網服務器是否可用,其中包含了兩個規則。
<directive id="500000" name="Public Web Server unavailable" priority="1">
<rule type="detector" name="server unavailable" reliability="1" occurrence="1" from="192.168.11.100" to="ANY" port_from="ANY" port_to="ANY" plugin_id="1525" plugin_sid="1,7,9"> <rules> <rule type="monitor" name="Ping Baidu Server in order to check internet connection" reliability="10" from="www.baidu.com" to="www.baidu.com" plugin_id="2009" plugin_sid="1" condition="gt" value="0" interval="20" time_out="120" /> </rules>
</directive>
關鍵參數解釋:
● Detector: 探測器規則自動收集從代理髮來的記錄,包括Snort、Apache、Arpwatch等。
● Monitor:監控器負責查詢Ntop服務發來的數據和會話。
● Name:事件數據庫中的規則名稱。
● Reliability:可靠性
● Plugin_id:插件ID,查看更多插件ID請參考《開源安全運維平臺OSSIM最佳實踐》第一章內容。
● Plugin_sid:插件子ID號,分配給每一個插件事件的子ID,好比Snort這個插件ID號爲1001,而1501就是它的子ID號,表明Apache事件的響應代碼,固然可不止這一件。
● Condition:條件參數和下面6個邏輯有關係,必須符合的邏輯條件匹配規則以下:
Ø eq – 等於(Equal)
Ø ne – 不等於(Not equal)
Ø lt – 小於(Lesser than)
Ø gt – 大於(Greater than)
Ø le – 小於等於(Lesser or equal)
Ø ge – 大於等於(Greater or equal)
●Interval:間隔,這個值相似於time_out,用於監控類規則。
3.Alienvault-scan規則描述
再舉一個OSSIM自帶的例子,咱們查看/etc/ossim/server/alienvault-scan.xml這個掃描Gong JI場景的策略文件,描述的結構就像個邏輯樹,基本格式以下:
Gree:level 1
Yellow : level2
Orange:level3 Red: level 4
下面給出部分代碼內容,如圖8所示
image.png
圖8 Gong JI掃描指令示例
● Occurrence,表示發生次數,默認爲1,Gong JI場景不一樣這個值也不同。這個值越大,越要引發管理員的警覺。這裏表示的發生次數,也就是計算具備相同的 "from、to、port_from、port_to、plugin_id、plugin_sid" 發生次數,用以進行到關聯模式中的下一規則。
這個數值在基於規則的關聯分析中很是有用,例如當目標IP地址發生的異常行爲事件數量的頻率達到了必定數值時(某人針對該系統發動Gong JI),OSSIM會發出預警提示,管理員就能夠有針對性開展深刻調查。固然對源IP也適用。
From表示來源,源地址有如下幾種形式:
①ANY,任意IP地址均可以匹配。
②小數點和數字的IPv4形式。
③以逗號隔開的IPv4地址,不帶掩碼。
④可使用任意數目的IP地址,中間用逗號隔開。
⑤網絡名稱,可使用網絡中事先定義好的網絡名稱。
⑥相對值,這種狀況比較複雜,能夠引用上條規則中的IP地址,例如:
l 1:SRC_IP 表示引用前一條規則的源地址
l 2:DST_IP 表示引用前第二條的目的地址做爲源地址
⑦否認形式,可使用地址的否認形式如 :"!192.168.150.200,HOME_NET"。
若是 HOME_NET = 192.168.150.0/24 將匹配一個C類子網排除192.168.150.200。
l Time_out,表示超時,其等待必定時間以匹配規則,時間超出則匹配失敗。
l Port_from/Port_to ,表示來自哪裏/目的端口,Port_from能夠是ANY,Port_to,能夠是一個端口號或一個逗號分隔的端口序列,1:DST_PORT,也能夠否認端口例如,port=「!22,25」。
注意:dst_ip表示目的ip地址,而dst_port則表示目的端口號,ipaddr本地ip地址。
l Protocol(協議),可使用如下字符串:TCP、UDP、ANY。
l Plugin_id(插件ID),參考plugin中的plugin_id。
l Plugin_sid(插件SID),每一個事件都是分配一個子ID。
image.png
圖9 規則樹的嵌套
在OSSIM系統運行前,必須爲已知的Gong JI場景創建對應的樹形規則集,在啓動時,系統將預先定義好的指令讀入內存,在接收到一個事件 (event)後,先將該event與以前已經匹配,而尚未匹配完的指令中的規則進行匹配,而後在於其餘規則匹配。那麼在一個複雜的Gong JI場景中一條Event就會與多條規則匹配,若是此事件的風險值超過預先設定的閾值,則將其alarm屬性設爲真,並在Alarm界面中顯示。
例如:plugin_id="1001" plugin_sid="2008609,2008641"。
在OSSIM 4.6系統中,有385個數據源,這裏ID=1001,表明Snort檢測插件,產品類型屬於IDS,主要適用於Snort規則,其它插件ID還記得嗎?若是忘了請返回本書第1章,查看「插件&功能」對應表。
實際上在OSSIM系統中,Snort插件ID範圍是1001~1145。在OSSIM 4.8 版中位於Configuration→Threat Intelligence→Data Source能夠查看到全部數據源。如圖10所示。
image.png
圖10 數據源分類
在Ossim的關聯引擎運行以前,必須爲全部已知的Gong JI場景創建對應的樹形指令(在開源系統中提供了84條,在OSSIM 4.15的商業版本提供了1800餘條,OSSIM USM 5.x提供2100+條),這也是它的核心價值的體現,在OSSIM啓動時,系統會將全部預先定義好的指令讀入內存,在接收到一個directive_event後,先將該事件與以前已經匹配,而尚未匹配完的指令中的規則匹配,而後再與其它指令的規則匹配。注意一個事件能夠與不少指令中的規則匹配。
5、 完善規則
OSSIM系統中的關聯規則生成主要經過安全專家人工編寫,這種方式效率低下,且人工成本難以承受. 對於新出現的Gong JI和漏洞沒法及時做出響應,檢測規則的編寫每每出現滯後的狀況, 你們也許會考慮可否利用AI技術和數據融合技術進行智能化的數據挖掘呢,這些剛高級的黑科技在實際應用中每每生成的關聯規則檢測精度較低,檢測結果不理想,實際應用效果有限。利用人工神經網絡來自動生成關聯規則,是關聯分析研究領域從此發展的方向。
對於新手而言從一張白紙開始寫規則有些難了,可是對照系統給出的默認規則,照葫蘆畫瓢仍是能夠實現的,無論這個模型是否完善,先用起來,而後逐步修改。在合適的時間,對本身進行,而後監控SIEM的反應,觀察它是否產生正確的警報,而警報是否提供足夠的信息來協助相應這弄清楚發生了什麼威脅,若是沒有那就須要修改規則,而後你須要不斷的優化閾值,你是否發現SIEM報警過於頻繁,或者很是稀少,你須要調節閾值來解決,順便說一句,面對動態的網絡Gong JI,這個調節的過程沒有終點若是讀者在學習關聯規則的過程當中遇到各類問題也能夠參考個人新書《開源安全運維平臺OSSIM疑難解析:提升篇》*。
附件:
下面分享的是OSSIM關聯分析的一部分源代碼。
/* ** * 該指令是否與根節點指令匹配,這裏只檢查根節點,並不檢查指令的子節點** */gboolean sim_directive_match_by_event (SimDirective *directive, SimEvent *event) { SimRule *rule; gboolean match; g_return_val_if_fail (directive, FALSE); g_return_val_if_fail (SIM_IS_DIRECTIVE (directive), FALSE); g_return_val_if_fail (!directive->_priv->matched, FALSE); g_return_val_if_fail (directive->_priv->rule_root, FALSE); g_return_val_if_fail (directive->_priv->rule_root->data, FALSE); g_return_val_if_fail (SIM_IS_RULE (directive->_priv->rule_root->data), FALSE); g_return_val_if_fail (event, FALSE); g_return_val_if_fail (SIM_IS_EVENT (event), FALSE); rule = SIM_RULE (directive->_priv->rule_root->data); match = sim_rule_match_by_event (rule, event); return match; }/* ** *這將檢查事件是否能夠與backlog中的某些數據匹配。backlog其實是一個包含事件數據的指令。每一個backlog條目都是一個樹,其中包含來自一個指令的全部規則(它至關因而一個指令克隆)。其中每一個規則(simrule)還包含與規則匹配的事件的數據。** * */gboolean sim_directive_backlog_match_by_event (SimDirective *directive, SimEvent *event) { GNode *node = NULL; g_return_val_if_fail (directive, FALSE); g_return_val_if_fail (SIM_IS_DIRECTIVE (directive), FALSE); g_return_val_if_fail (!directive->_priv->matched, FALSE); g_return_val_if_fail (directive->_priv->rule_curr, FALSE); g_return_val_if_fail (directive->_priv->rule_curr->data, FALSE); g_return_val_if_fail (SIM_IS_RULE (directive->_priv->rule_curr->data), FALSE); g_return_val_if_fail (event, FALSE); g_return_val_if_fail (SIM_IS_EVENT (event), FALSE); node = directive->_priv->rule_curr->children; while (node) //**咱們必須對照backlog中的全部規則節點檢查事件,除了根節點,由於它簽入了sim_directive_match_by_event是從sim_organizer_correlation調用的.** { SimRule *rule = (SimRule *) node->data; if (sim_rule_match_by_event (rule, event)) { g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "sim_directive_backlog_match_by_event; sim_rule_match_by_event: True"); time_t time_last = time (NULL); directive->_priv->rule_curr = node; // 每次事件匹配時,該指令都下一級到匹配的節點。下次將根據此級別檢查事件。 //FIXME: 父節點中可能存在內存泄漏. directive->_priv->time_last = time_last; directive->_priv->time_out = sim_directive_get_rule_curr_time_out_max (directive); sim_rule_set_event_data (rule, event); //這裏咱們將事件中的各個字段分配到規則中,因此每次咱們進入規則時,咱們能夠看到匹配的事件. sim_rule_set_time_last (rule, time_last); if (!G_NODE_IS_LEAF (node)) { GNode *children = node->children; while (children) { SimRule *rule_child = (SimRule *) children->data; sim_rule_set_time_last (rule_child, time_last); sim_directive_set_rule_vars (directive, children); children = children->next; g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "sim_directive_backlog_match_by_event: There are childrens in %d directive", directive->_priv->id); } } else { directive->_priv->matched = TRUE; g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "sim_directive_backlog_match_by_event: The directive %d has matched", directive->_priv->id); } return TRUE; } else { g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "sim_directive_backlog_match_by_event: sim_rule_match_by_event: False"); } node = node->next; } return FALSE; }/* * 檢查指令中的全部節點規則,以查看....... */gboolean sim_directive_backlog_match_by_not (SimDirective *directive) { GNode *node = NULL; GNode *children = NULL; g_return_val_if_fail (directive, FALSE); g_return_val_if_fail (SIM_IS_DIRECTIVE (directive), FALSE); g_return_val_if_fail (!directive->_priv->matched, FALSE); g_return_val_if_fail (directive->_priv->rule_curr, FALSE); g_return_val_if_fail (directive->_priv->rule_curr->data, FALSE); g_return_val_if_fail (SIM_IS_RULE (directive->_priv->rule_curr->data), FALSE); node = directive->_priv->rule_curr->children; while (node) { SimRule *rule = (SimRule *) node->data; //若是規則已超時 && if ((sim_rule_is_time_out (rule)) && (sim_rule_get_not (rule)) && (!sim_rule_is_not_invalid (rule))) { time_t time_last = time (NULL); directive->_priv->rule_curr = node; directive->_priv->time_last = time_last; directive->_priv->time_out = sim_directive_get_rule_curr_time_out_max (directive); sim_rule_set_not_data (rule); if (!G_NODE_IS_LEAF (node)) //這不是最後的節點,他還有一些子節點. { children = node->children; while (children) { SimRule *rule_child = (SimRule *) children->data; sim_rule_set_time_last (rule_child, time_last); sim_directive_set_rule_vars (directive, children); children = children->next; } } else //last node! { directive->_priv->matched = TRUE; } return TRUE; } node = node->next; } return FALSE; }/* * backlog&directives幾乎是相同的:backlog是存儲指令並填充事件數據的地方。 *「node」是子節點函數。咱們須要從引用其級別的節點向該節點添加src_ip、port等。若是「node」參數是根節點->子節點1->子節點2中的children2,而且咱們在children2中有1:plugin-sid,那麼咱們必須將根節點中的plugin-sid添加到children2中。 */void sim_directive_set_rule_vars (SimDirective *directive, GNode *node) { SimRule *rule; SimRule *rule_up; GNode *node_up; GList *vars; GInetAddr *ia; GInetAddr *sensor; gint port; gint sid; SimProtocolType protocol; gchar *aux = NULL; g_return_if_fail (directive); g_return_if_fail (SIM_IS_DIRECTIVE (directive)); g_return_if_fail (node); g_return_if_fail (g_node_depth (node) > 1); rule = (SimRule *) node->data; vars = sim_rule_get_vars (rule);