http://thisissecurity.net/2015/11/23/hackers-do-the-haka-part-1/
Haka是一種開源的以網絡安全為導向的語言,可以用于編寫安全規則和協議剝離器。在這一部分中,我們的重點是編寫安全規則。
Haka是一種開源的以網絡安全為導向的語言,可以在捕捉到的活動流量上指定和應用安全策略。Haka基于Lua。這是一種簡單、輕量(~200 kB)且快速的(有一個可用的JiT編譯器)腳本語言。
Haka的使用范圍有兩種。首先,Haka能允許指定安全規則來過濾掉不想要的流并報告惡意活動。Haka提供了一個簡單的API用于操作高級數據包和流。用戶可以投放數據包,或創建新的數據包,并注入數據包。Haka還支持修改運行中的數據包。這是Haka的主要功能之一,因為用戶可以看到所有的復雜任務,比如調整數據包的大小,設置正確的序列號。這些都是現場完成的,根本不需要代理。
其次,Haka還附帶有一種語法,允許協議規范及其底層的狀態機。Haka支持兩種類型的協議:基于二進制的協議(如,dns)和基于文本的協議(如,http)。這種規范包括了基于數據包的協議(如ip)以及基于流的協議(如http)。
Haka內嵌到了一個模塊化框架中,其中包括幾個數據包捕捉模塊(pcap, nfqueue),能允許終端用戶在實時捕捉到的流量上應用自己的安全策略,或者是在一個數據包跟蹤文件上重現這個安全策略。這個框架還提供了記錄(syslog)和報警模塊(syslog,elasticsearch)。報警遵循了一種類似IDMED的格式。最后,這個框架還具有附屬模塊,比如模式匹配引擎和一個指令反匯編模塊。這些模塊允許編寫精密的安全規則來檢測經過混淆的木馬。因為Haka是按照模塊方式設計的,所以用戶可以通過額外的模塊來擴展其功能。
Haka提供了一個包含有4個工具的套件:
haka.這是工具集中的主程序。這是一個守護進程,用于監控后臺中的數據包。Haka會根據指定的安全策略文件來分析和過濾這些數據包。例如,下面的配置樣本會要求Haka使用nfqueue模塊從接口eth0中捕捉數據包,并使用策略文件myrules.lua過濾這些數據包。這個腳本通常會加載用戶定義或內置的協議剝離器,并定義一系列的安全規則。另外,用戶可以選擇報警和報告模塊并設置一些特定的模塊選項:
[general]
# Select the haka configuration file to use
configuration = "myrules.lua"
# Optionally select the number of thread to use
# By default, all system thread will be used
#thread = 4
[packet]
# Select the capture model, nfqueue or pcap
module = "packet/nfqueue"
# Select the interfaces to listen to
#interfaces = "any"
interfaces = "eth0"
# Select packet dumping for nfqueue
#dump = yes
#dump_input = "/tmp/input.pcap"
#dump_output = "/tmp/output.pcap"
[log]
# Select the log module
module = "log/syslog"
# Set the default logging level
#level = "info,packet=debug"
[alert]
# Select the alert module
module = "alert/syslog"
#module = "alert/file"
#module = "alert/elasticsearch"
# Disable alert on standard output
#alert_on_stdout = no
hakactl. 這個工具允許控制一個運行的Haka守護進程。用戶可以實時分析捕捉到的數據包,檢查日志或簡單地關停/重啟守護進程。
hakapcap. 這個工具允許使用pcap模塊在數據包捕捉跟蹤上離線重現一個策略文件。例如,這樣對執行網絡分析非常有用。
hakabana.這個工具允許使用Kibana 和 Elasticsearch實時地可視化和監控網絡流量。Hakabana由一系列的自定義安全規則組成,這些規則會把流量信息通過Haka推送到一個elastisserach服務器,并讓這些流量能通過Kibana控制面板獲取到。另外一個控制板也可以可視化Haka警報。
Haka提供了一種簡單的方式來編寫安全規則,從而過濾,修改,創建,注入數據包和流。當檢測到一個惡意流后,用戶可以報告一個警報或放棄這個流。用戶可以定義更多復雜的方案來應對某次攻擊所造成的影響。例如,用戶可以報警http請求,強制舊版瀏覽器更新或偽造特定的數據包來欺騙端口掃描工具。
下面的這個規則是一個基礎的數據包過濾規則,能夠攔截所有到某個網絡地址的連接。
local ipv4 = require("protocol/ipv4")
local tcp = require("protocol/tcp_connection")
local net = ipv4.network("192.168.101.0/24")
haka.rule{
hook = tcp.events.new_connection,
eval = function (flow, pkt)
haka.log("tcp connection %s:%i -> %s:%i",
flow.srcip, flow.srcport,
flow.dstip, flow.dstport)
if net:contains(flow.dstip) then
haka.alert{
severity = "low",
description = "connection refused",
start_time = pkt.ip.raw.timestamp
}
flow:drop()
end
end
}
第一行會加載需要的協議剝離器,也就是ipv4和tcp連接剝離器。前者是處理ipv4數據包。后者是一個狀態性的tcp剝離器,這個剝離器會維持一個連接表并管理tcp流。下一行,定義了必須要攔截的網絡地址。
這種安全規則是通過haka.rule關鍵字定義的。一個安全規則由一個hook和一個評估函數eval組成。這個hook是一個會觸發安全規則評估的事件。在這個例子中,在每次嘗試創建一個tcp連接時,這個安全規則就會被評估。傳遞到評估函數的參數會根據事件來確定。以new_connection事件為例,eval會獲取兩個參數:flow和pkt。第一個參數中會有關于連接的詳細信息,另一個參數一個包含有所有tcp(以及下層)數據包字段的表。
在安全規則的核心中,我們首先記錄(haka.log)了一些關于當前連接的信息。然后,我們檢查了源地址是否屬于先前定義的非授權IP地址范圍。如果測試成功,我們就會發出警報(haka.alert)并放棄連接。注意,我們只在警報中報告了少量的一些細節。用戶可以添加更多信息,比如來源和目標服務。
我們使用hakapcap工具在一個pcap追蹤文件filter.pcap上,測試了我們的規則filter.lua:
$ hakapcap filter.lua filter.pcap
從這里往下就是Haka的輸出,Haka轉儲了一些關于已加載剝離器和已注冊規則的信息。這個輸出顯示Haka成功攔截了目標地址192.168.101.62的連接:
在上面的例子中,我們已經定義了一個單獨的規則來攔截連接。用戶可以用關鍵字haka.group寫一個類似于防火墻一樣的完整規則集。以這個配置為例,如果沒有任何安全規則能認證流量,用戶可以選擇一種默認行為(如攔截所有的連接)。
在Haka中,用戶可以創建新的數據包并注入這些數據包。下面的這個規則會制作一個RST數據包,用于欺騙Xmas nmap掃描。最終,nmap會認為目標端上的所有端口都是關閉的。
raw = require("protocol/raw")
ipv4 = require("protocol/ipv4")
tcp = require("protocol/tcp")
haka.rule {
hook = tcp.events.receive_packet,
eval = function(pkt)
local flags = pkt.flags
-- test for xmas nmap scans
if flags.fin and flags.psh and flags.urg then
-- raw packet
local rstpkt = raw.create()
-- ip packet
rstpkt = ipv4.create(rstpkt)
rstpkt.ttl = pkt.ip.ttl
rstpkt.dst = pkt.ip.src
rstpkt.src = pkt.ip.dst
-- tcp packet
rstpkt = tcp.create(rstpkt)
rstpkt.srcport = pkt.dstport
rstpkt.dstport = pkt.srcport
rstpkt.flags.rst = true
rstpkt.flags.ack = true
rstpkt.ack_seq = pkt.seq + 1
-- inject forged packet and
-- drop malicious scanning packet
rstpkt:send()
pkt:drop()
end
end
}
數據包修改是Haka中最高級的功能之一。Haka會在流和數據包層級上自動處理所有的內部修改:重新設置數據包大小和分段,重置序列號等。下面的例子證明了訪問和修改協議字段有多么容易。這個規則會修改一些http協議的標頭。更準確的說, user-agent標頭會被修改(如果沒有設置,添加至標頭列表),并移除accept-encoding標頭。
local http = require("protocol/http")
http.install_tcp_rule(80)
haka.rule{
hook = http.events.request,
eval = function (flow, request)
request.headers["User-Agent"] = "HAKA User Agent"
request.headers["Accept-Encoding"] = nil
end
}
blurring-the-web和inject_ponies是非常有意思的腳本,會通過修改http響應流量來分別模糊和污染(注入垃圾)被請求的web頁面:
在講解流過濾前,我們首先要說明的是Haka如何在內部管理數據包和流。在Haka中,所有的數據包和流都會用虛擬緩沖區(見下圖)來表示。虛擬緩沖區是一種非相鄰內存塊的統一視圖。這些虛擬緩沖區能允許簡單和有效的修改內存數據。虛擬緩沖區使用分散列表來表示非相鄰數據塊,避免分配和復制不必要的內存塊。Haka提供了迭代器來導航通過這些內存塊。這些迭代器可以通過攔截讓停用一些函數,然后,比如當流上有更多可用的數據時,透明地恢復這些函數的執行。
下面的規則會收集http流,并在stdout上轉儲這些流。這個規則等同于Wireshark的follow tcp stream”功能。
local ipv4 = require('protocol/ipv4')
local tcp_connection = require('protocol/tcp_connection')
haka.rule{
hook = tcp_connection.events.receive_data,
options = {
streamed = true
},
eval = function (flow, iter, dir)
local data = flow.ccdata or {}
flow.ccdata = data
while iter:wait() do
data[#data+1] = iter:sub('available'):asstring()
end
haka.log("%s -> %s:\n", flow.srcip, flow.dstip)
io.write(table.concat(data))
end
}
這是我最喜歡的Haka功能。這個功能允許檢查每個數據包的流量包。下面的規則會提示每個HTTP POST請求。
local http = require("protocol/http")
http.install_tcp_rule(80)
haka.rule {
hook = http.events.request_data,
eval = function (http, data)
haka.interactive_rule("interactive mode")(http, data)
end
}
haka.rule {
hook = http.events.request,
eval = function (http, request)
http:enable_data_modification()
end
}
這個shell能夠提供到完整Haka API的訪問,以便處理數據包內容:讀寫和修改數據包字段,刪除數據包,記錄可疑的事件,警告等。Lua控制板支持自動補齊,因此,是深入Haka API的一個好的開始。
在下面的數據中,Haka會破解第一個POST請求。HTTP數據可以通過可用的輸入來獲取。在這個例子中,我們在運行中修改了用戶憑據。
注意,最好在pcap文件上使用交互規則,因為修改會造成額外的延遲。
Haka還有一個模式匹配引擎和一些反匯編模塊。這兩個模塊都是基于流的模塊,能讓我們檢測到分散在多個數據包中的惡意有效載荷。下面的規則使用了一個常規表達來檢測nop sled。我們啟用了流選項,也就是說,匹配函數會攔截和等待可用的數據來進行匹配。如果檢測到nop sled,我們就會發出警告,并轉儲shellcode指令。注意,模式匹配函數會更新迭代器的位置,之后會指向shellcode。
local tcp = require("protocol/tcp_connection")
local rem = require("regexp/pcre")
local re = rem.re:compile("%x90{100,}")
local asm = require("misc/asm")
local dasm = asm.new_disassembler("x86", "32")
haka.rule{
hook = tcp.events.receive_data,
options = {
streamed = true,
},
eval = function (flow, iter, direction)
if re:match(iter, false) then
-- raise an alert
haka.alert{
description = "nop sled detected",
}
-- dump instructions following nop sled
dasm:dump_instructions(iter)
end
end
}
我們在著名的網絡分析挑戰上重播了這條規則,并得到了下面的輸出。關于網絡流量反匯編為指令的詳細信息都可以在這里獲得。
未完待續…