suricata規則分析
Suricata 簽名的結構
在高層次上,Suricata簽名由三部分組成:
- Action:當流量符合規則時採取的行動
- Header:一個標題,描述主機、IP地址、埠、協議和流量方向(傳入或傳出)
- Options:選項,指定諸如簽名ID(sid)、日誌資訊、匹配資料包內容的正規表示式、分型別別,以及其他可以幫助縮小識別合法和可疑流量的修飾語
簽名的一般結構如下:
ACTION HEADER OPTIONS
示例規則分析1
sid:2100498:
alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|";
簽名的alert部分是ACTION,ip any -> any any部分是HEADER,簽名的其餘部分從(msg:GPL ATTACK_RESPONSE...)開始包含了規則的OPTIONS。
Actions
sid:2100498
簽名的第一部分是Actions,在這裡是alert。Suricata簽名的Actions部分指定了當資料包符合規則時要採取的動作。根據Suricata是在IDS還是IPS模式下執行,行動還可以是以下之一:
- Pass - Suricata將停止掃描該資料包,並允許其透過,但不產生警報。
- Drop - 當在IPS模式下工作時,Suricata將立即停止處理該資料包併產生警報。如果產生資料包的連線使用的是TCP,則會超時。
- Reject - 當Suricata執行IPS模式時,將傳送一個TCP重置包,Suricata將放棄匹配的資料包。
- Alert - Suricata將生成一個警報,並將其記錄下來以便進一步分析。
Headers
每個Suricata簽名都有一個Headers部分,描述了網路協議、源和目的IP地址、埠和流量方向。參考示例 sid:2100498
簽名,該規則的頭部分是突出顯示的ip any any -> any any
部分:
alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)
一條規則的標題部分的一般格式是:
<PROTOCOL> <SOURCE IP> <SOURCE PORT> -> <DESTINATION IP> <DESTINATION PORT>
PROTOCOL協議可以是以下之一:
- TCP
- UDP
- ICMP
- IP
- 其他一些應用協議
來源和目的地欄位可以是IP地址或網路範圍,或者是特殊值any,它將匹配所有的IP地址和網路。
箭頭->表示流量的方向。
注意:簽名也可以使用非方向性標記<>,它將匹配兩個方向的流量。然而,Suricata關於方向性標記的檔案指出,大多數規則將使用->右側的匹配箭頭。
如果你想對惡意的出站流量(即離開你的網路的流量)發出警報,那麼源欄位將是你的系統的IP地址或網路範圍。目的地可以是一個遠端系統的IP或網路,或特殊的任何值。
反過來說,如果你想對傳入的惡意流量產生警報,源欄位可以設定為任何,而目的地可以是你係統的IP地址或網路範圍。
你還可以使用埠欄位指定要檢查的TCP或UDP埠。一般來說,來自一個系統的流量會被分配一個隨機的埠,所以任何值對->指標的左邊是合適的。如果你打算檢查每個傳入資料包的內容,目標埠也可以是任何,或者你可以限制一個簽名,只掃描個別埠的資料包,如22用於SSH流量,或443用於HTTPS。
sid:2100498的ip any -> any any
頭是一個通用的頭,將匹配所有的流量,無論協議、源或目標IP或埠。當你想確保入站和出站流量被檢查出可疑的內容時,這種捕獲所有的頭是有用的。
請注意,源、目的和埠欄位也可以使用特殊的 !否定運運算元,它將處理與該欄位值不匹配的流量。
例如,以下簽名將使Suricata對所有來自任何網路的SSH資料包發出警報,這些資料包的目的地是你的網路(由203.0.113.0/24 IP塊代表),而不是以22埠為目的地:
alert ssh any any -> 203.0.113.0/24 !22 (sid:1000000;)
這種警報並不那麼有用,因為它不包含任何關於資料包的資訊,也不包含分型別別。為了給警報新增額外的資訊,以及根據更具體的標準進行匹配,Suricata規則有一個OPTIONS部分,你可以為一個簽名指定一些額外的設定。
OPTIONS
在Suricata簽名中的括號(...)內的引數包含各種選項和關鍵字修改器,你可以用它們來匹配資料包的特定部分,對規則進行分類,或記錄自定義資訊。規則的header引數是針對IP、埠和協議級別的資料包標題,而OPTIONS則是針對資料包中的資料進行匹配。
Suricata規則中的OPTIONS必須用分號隔開,並且通常使用key:value格式。有些選項沒有任何設定,只需要在規則中指定名稱。
使用上一節的簽名示例,你可以新增msg選項(即觸發規則後返回的提示資訊),其值為在非SSH埠檢測到的SSH流量,解釋警報的內容:
alert ssh any any -> 203.0.113.0/24 !22 (msg:"SSH TRAFFIC on non-SSH port"; sid:1000000;)
關於如何在Suricata規則中使用每個選項的完整解釋,從第6.2節開始的Suricata規則檔案詳細描述了每個關鍵詞選項。
然而,有一些核心選項,如內容關鍵字和各種Meta關鍵字,在大多數簽名中都會用到,我們將在下面的章節中研究:
關鍵字:Content
任何規則最重要的選項之一是Content內容關鍵詞。回顧一下sid:2100498簽名的例子:
alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)
突出顯示的內容: "uid=0|28|root|29|";
部分包含Content關鍵字,以及Suricata將在資料包內尋找的值。在這個簽名示例中,來自任何埠的任何IP地址的所有資料包都將被檢查,以確保它們不包含字串值uid=0|28|root|29|(在以前的教程中,它被用作表示被攻擊的主機的例子)
Content關鍵字可以與Suricata中的大多數其他關鍵字一起使用。你可以使用標頭檔案的組合來建立非常具體的簽名,以及針對特定應用協議的選項,然後使用正規表示式檢查資料包內容的單個位元組、字串或匹配。
例如,下面的簽名檢查DNS流量,尋找任何內容為your_domain.com的資料包,並生成一個警報:
alert dns any any -> any any (msg:"DNS LOOKUP for your_domain.com"; dns.query; content:"your_domain.com"; sid:1000001;)
然而,如果DNS查詢使用域名YOUR_DOMAIN.COM,則此規則將無法匹配,因為Suricata預設為大小寫內容匹配。要使內容匹配對大小寫不敏感,請在規則中新增nocase;
關鍵字。
alert dns any any -> any any (msg:"DNS LOOKUP for your_domain.com"; dns.query; content:"your_domain.com"; nocase; sid:1000001;)
現在,小寫或大寫字母的任何組合仍將與內容關鍵詞相匹配。
關鍵字msg
本教程中的簽名示例都包含了帶有簽名資訊的msg關鍵字。雖然msg選項不是必須的,但留空的話,在檢查Suricata的日誌時,就很難理解為什麼會發生警報或刪除動作。
msg選項的設計是對一個警報的可讀文字描述。它應該是描述性的,併為警報新增上下文,以便您或其他正在分析日誌的人理解為什麼警報被觸發。在本教程的reference Keyword部分,你將瞭解到參考選項,你可以用它來連結到關於簽名和它所要檢測的問題的更多資訊。
關鍵字 sid
和 rev
每個Suricata簽名都需要一個唯一的簽名ID(sid)。如果兩個規則具有相同的sid(在下面的輸出示例中是sid:10000000),Suricata將不會啟動,而會產生一個類似下面的錯誤:
Example Duplicate sid Error. . .
19/11/2021 -- 01:17:40 - <Error> - [ERRCODE: SC_ERR_DUPLICATE_SIG(176)] - Duplicate signature "drop ssh any any -> 127.0.0.0/8 !22 (msg:"blocked invalid ssh"; sid:10000000;)"
. . .
當你建立自己的簽名時,1000000-1999999的範圍被保留給自定義規則。Suricata的內建規則的範圍是2200000-2299999。其他邊框範圍在新出現的威脅SID分配頁面上有記錄。
sid選項通常是Suricata規則的最後部分。然而,如果一個簽名有多個版本,並隨著時間的推移而變化,則有一個rev選項,用於指定規則的版本。例如,本教程早期的SSH警報可以改為只掃描2022埠的SSH流量:
alert ssh any any -> 203.0.113.0/24 2022 (msg:"SSH TRAFFIC on non-SSH port"; sid:1000000; rev:2;)
更新後的簽名現在包括rev:2選項,表明它已經從以前的版本更新。
關鍵字reference
reference參考關鍵詞在簽名中用來描述在哪裡可以找到更多關於規則所要檢測的攻擊或問題的資訊。例如,如果一個簽名是為了檢測一種新的漏洞或攻擊方法,參考欄位可以用來連結到一個安全研究員或公司的網站,記錄這個問題。
OpenSSL中的Heartbleed漏洞就是一個被廣泛宣傳和研究的漏洞的例子。Suricata帶有簽名,旨在檢查不正確的TLS資料包,幷包括對Heartbleed CVE主條目的參考:
alert tls any any -> any any (msg:"SURICATA TLS invalid heartbeat encountered, possible exploit attempt (heartbleed)"; flow:established; app-layer-event:tls.invalid_heartbeat_message; flowint:tls.anomaly.count,+,1; classtype:protocol-command-decode; reference:cve,2014-0160; sid:2230013; rev:1;)
請注意簽名中突出顯示的參考:cve,2014-0160;
部分。這個參考選項告訴您或正在檢查Suricata警報的分析師,在哪裡可以找到有關該特定問題的更多資訊。
參考選項可以使用/etc/suricata/reference.config
檔案中的任何字首。例如,在前面的例子中,可以用url來代替cve,用一個直接指向Heartbleed網站的連結來代替2014-0160 CVE標識。
關鍵字classtype
Suricata可以根據一套預先配置好的類別對流量進行分類,這些類別在你用Linux發行版的軟體包管理器安裝Suricata軟體包時就已經包含了。預設的分類檔案通常在/etc/suricata/classification.config
中找到,包含如下條目:
#
# config classification:shortname,short description,priority
#
config classification: not-suspicious,Not Suspicious Traffic,3
config classification: unknown,Unknown Traffic,3
config classification: bad-unknown,Potentially Bad Traffic, 2
. . .
如檔案頭所示,每個分類條目有三個欄位:
- shortname:一個簡短的、機器可讀的名字,在上面的例子中分別是:not-suspicious、unknown和bad-unknown
- short description:用於警報的分類描述,例如:Not Suspicious Traffic
- priority:一個優先順序欄位,它決定了簽名將被Suricata處理的順序。最高的優先順序是值1。當Suricata處理一個資料包時,使用更高優先順序的分類器的簽名將被首先檢查。
在 sid:2100498
簽名的例子中,classtype 是classtype:bad-unknown;
alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)
簽名的隱含優先順序是2,因為這是在/etc/suricata/classification.config
中分配給 **bad-unknown classtype **的值。如果你想覆蓋一個 classtype 的預設優先順序,你可以在簽名中新增一個priority:n
選項,其中n是一個從1到255的值。
關鍵字 target
Suricata簽名中另一個有用的選項是target目標選項。它可以被設定為兩個值之一:src_ip和dest_ip。這個選項的目的是為了在Suricata的警報日誌中正確識別源主機和目標主機。
例如,本教程前面的SSH簽名可以用target:dest_ip;選項來加強:
alert ssh any any -> 203.0.113.0/24 2022 (msg:"SSH TRAFFIC on non-SSH port"; target:dest_ip; sid:1000000; rev:3;)
這個例子使用dest_ip是因為這個規則被設計為檢查進入我們的例子網路的SSH流量,所以它是目標。在規則中新增目標選項將導致在 **eve.json **日誌條目的alert部分出現以下額外欄位:
. . .
"source": {
"ip": "127.0.0.1",
"port": 35272
},
"target": {
"ip": "203.0.113.1",
"port": 2022
}
. . .
有了Suricata日誌中的這些條目,它們可以被髮送到安全資訊和事件管理(SIEM)工具中,以便更容易地搜尋可能來自普通主機的警報,或針對網路上特定目標的攻擊。
示例規則分析2
有如下規則,下面對其進行解釋
alert tcp $EXTERNAL_NET any -> 10.200.0.0/24 80 (msg:"WEB-IIS CodeRed v2 root.exe access"; flow:to_server,established; uricontent:"/root.exe"; nocase; classtype:web application-attack; reference:url,www.cert.org/advisories/CA-2001 19.html; sid:1255; rev:7;)
alert:告訴Suricata將此行為作為警報報告(在為STA建立的規則中是強制性的)。
tcp: 表示此規則只適用於TCP的流量。
$EXTERNAL_NET:這是在Suricata中定義的一個變數。
預設情況下,變數HOME_NET被定義為這些範圍內的任何IP:192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,而EXTERNAL_NET則定義為這些範圍之外的任何IP。
你可以透過指定單個IP如10.200.0.0、IP CIDR範圍如192.168.0.0/16或IP列表如[192.168.0.0/16,10.0.0.8]來指定IP地址。請注意,列表中的空格是不允許的。
any:在這種情況下,它意味著 "來自任何源埠",然後有一個箭頭'->',意味著 "連線到"(沒有'<-'運運算元,但你可以簡單地翻轉運運算元周圍的引數。你可以使用'<>'運運算元來表示連線方向與此規則無關),然後是一個IP範圍,表示目標IP地址,然後是埠。你可以用冒號來表示一個埠範圍,比如0:1024表示0-1024。在圓括號中,有一些指令用於設定警報資訊、關於規則的後設資料,以及額外的檢查。
msg: 是一個指令,它簡單地設定了在檢測到匹配流量的情況下將傳送的資訊(在STA情況下傳送到Coralogix)。
flow: 是一個指令,表示我們即將定義為簽名的內容是否需要出現在與伺服器("to_server")或與客戶("to_client")的通訊中。這可能非常有用,例如,如果我們想檢測伺服器的響應,該項可表明它已被攻破。
established: 是一個指令,它將導致Suricata限制其搜尋匹配此簽名的資料包,只搜尋屬於已建立連線的資料包。這對於儘量減少Suricata的負載是很有用的。
uricontent: 是一個指令,指示Suricata在規範化的HTTP URI內容中尋找某個文字。在這個例子中,我們要尋找的url正是"/root.exe "這樣的文字。
nocase:是一個指令,表示我們希望Suricata進行不區分大小寫的搜尋。
classtype:是一個指令,它是一個後設資料屬性,表明該規則檢測的活動型別。
reference:是一個指令,是一個後設資料屬性,連結到另一個系統以獲取更多資訊。在我們的例子中,值url,https://....連結到網際網路上的一個URL。
sid: 是一個指令,是一個後設資料屬性,表示簽名的ID。如果你正在建立你自己的簽名(即使你只是替換一個內建的規則),請使用一個高於9,000,000的值,以防止與另一個預先存在的規則發生碰撞。
rev: 是一個指令,表示規則的版本。
編寫suricata規則的技巧
針對漏洞,而不要漏洞利用
避免編寫檢測特定漏洞工具包的規則,因為同樣的漏洞有無數個漏洞,而且我們可以肯定,在你讀到這篇文章的時候,新的漏洞正在被編寫。例如,許多早期檢測緩衝區超限攻擊的簽名是這樣的:
alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (content:"AAAAAAAAAAAAAA", msg:"Buffer overrun detected.")
其原因當然是為了成功地發起緩衝區超限攻擊,攻擊者需要填充某個變數的緩衝區,並在最後新增他的惡意有效載荷,使其成為可執行檔案。他選擇用來填充緩衝區的字元是完全不重要的,事實上,在這種簽名出現後,許多攻擊工具箱只是用不同的字母來填充緩衝區,完全逃避了這種簽名檢測。一個更好的方法是試圖透過檢測基於欄位型別和長度的不正確輸入來檢測這類攻擊。