diff options
-rw-r--r-- | wireshark/sharkfest_scripts/README.md | 11 | ||||
-rw-r--r-- | wireshark/sharkfest_scripts/dns_request_reply_ratio.lua | 123 | ||||
-rw-r--r-- | wireshark/sharkfest_scripts/http_request_reply_ratio.lua | 125 | ||||
-rw-r--r-- | wireshark/sharkfest_scripts/tcp_no_data_exchanged.lua | 127 |
4 files changed, 386 insertions, 0 deletions
diff --git a/wireshark/sharkfest_scripts/README.md b/wireshark/sharkfest_scripts/README.md new file mode 100644 index 000000000..43d5b8d0f --- /dev/null +++ b/wireshark/sharkfest_scripts/README.md @@ -0,0 +1,11 @@ +# Companion Wireshark Scripts + +This folder contains some scripts we developed for the Sharkfest conference. They are used +to detect specific attacks and security flaws. + +In order to test these scripts you can use the following pcaps: +- https://github.com/NewBee119/ctf_ics_traffic +- https://www.netresec.com/?page=pcapfiles + +or pcaps from nDPI test directory +- https://github.com/ntop/nDPI/tree/dev/tests/pcap diff --git a/wireshark/sharkfest_scripts/dns_request_reply_ratio.lua b/wireshark/sharkfest_scripts/dns_request_reply_ratio.lua new file mode 100644 index 000000000..4cac059f4 --- /dev/null +++ b/wireshark/sharkfest_scripts/dns_request_reply_ratio.lua @@ -0,0 +1,123 @@ + +-- +-- Sharkfest 2021 +-- +-- This is going to be an example of a lua script that can be written for cybersecurity reasons. +-- DNS Request/Reply Ratio: + + +local f_dns_response_flag = Field.new("dns.flags.response") +local f_ip_src = Field.new("ip.src") +local f_ip_dst = Field.new("ip.dst") + +--############################################ + +local function getstring(finfo) + local ok, val = pcall(tostring, finfo) + if not ok then val = "(unknown)" end + return val +end + +--############################################ + +local function processResponse(dns_table, req_or_rep, src, dst) + local key = src .. "->" .. dst + + -- Create the table entry if needed + if not dns_table[key] then + dns_table[key] = { + requests = 0, + replies = 0, + } + end + + -- Increase the stats + dns_table[key][req_or_rep] = dns_table[key][req_or_rep] + 1 + + return dns_table +end + +--############################################ + +local function processPackets(pinfo,tvb, dns_table) + -- Call the function that extracts the field + local dns = f_dns_response_flag() + + --Check if there is an DNS request or reply + if dns then + if dns.value == false then + local src = getstring(f_ip_src().value) + local dst = getstring(f_ip_dst().value) + + dns_table = processResponse(dns_table, "requests", src, dst) + else + local dst = getstring(f_ip_src().value) + local src = getstring(f_ip_dst().value) + + dns_table = processResponse(dns_table, "replies", src, dst) + end + end + + return dns_table +end + +--############################################ + +local function dnsReqRepRatio() + -- Declare the window we will use + local tw = TextWindow.new("DNS Request/Reply Ratio") + + local dns_table = {} + + local tap = Listener.new(); + + local function removeListener() + -- This way we remove the listener that otherwise will remain running indefinitely + tap:remove(); + end + + -- We tell the window to call the remove() function when closed + tw:set_atclose(removeListener) + + -- This function will be called once for each packet + function tap.packet(pinfo,tvb) + dns_table = processPackets(pinfo,tvb, dns_table) + end + + -- This function will be called once every few seconds to update our window + function tap.draw(t) + tw:clear() + + for flow in pairs(dns_table) do + local requests = dns_table[flow]["requests"] + local replies = dns_table[flow]["replies"] + local ratio = 0 + local danger = "" + + if replies == 0 then + ratio = 0 + else + ratio = requests/replies + end + + if ratio ~= 1 then + danger = "-- DANGER: RATIO NOT 1 --\n" + end + + tw:append(danger .. flow .. ":\n\tRatio: " .. (ratio) .. "\n\tRequests: " .. requests .. "\n\tReplies: " .. replies .. "\n\n"); + end + end + + -- This function will be called whenever a reset is needed + -- e.g. when reloading the capture file + function tap.reset() + tw:clear() + dns_table = {} + end + + -- Ensure that all existing packets are processed. + retap_packets() +end + +-- Register the menu Entry +register_menu("Sharkfest/DNS Request-Reply Ratio", dnsReqRepRatio, MENU_TOOLS_UNSORTED)
\ No newline at end of file diff --git a/wireshark/sharkfest_scripts/http_request_reply_ratio.lua b/wireshark/sharkfest_scripts/http_request_reply_ratio.lua new file mode 100644 index 000000000..1e89ec033 --- /dev/null +++ b/wireshark/sharkfest_scripts/http_request_reply_ratio.lua @@ -0,0 +1,125 @@ + +-- +-- Sharkfest 2021 +-- +-- This is going to be an example of a lua script that can be written for cybersecurity reasons. +-- HTTP Request/Reply Ratio: +-- the ratio of HTTP requests and replies should be alwais close to 1, because, if not, usually means +-- that there are problems with the client that is sending the requests or there are problems with +-- the server that should receive those requests. + +local f_http_request = Field.new("http.request") +local f_http_reply = Field.new("http.response") +local f_ip_src = Field.new("ip.src") +local f_ip_dst = Field.new("ip.dst") + +--############################################ + +local function getstring(finfo) + local ok, val = pcall(tostring, finfo) + if not ok then val = "(unknown)" end + return val +end + +--############################################ + +local function processResponse(http_table, req_or_rep, src, dst) + local key = src .. "->" .. dst + + -- Create the table entry if needed + if not http_table[key] then + http_table[key] = { + requests = 0, + replies = 0, + } + end + + -- Increase the stats + http_table[key][req_or_rep] = http_table[key][req_or_rep] + 1 + + return http_table +end + +--############################################ + +local function processPackets(pinfo,tvb, http_table) + -- Call the function that extracts the field + local http_request = f_http_request() + local http_reply = f_http_reply() + + --Check if there is an HTTP request or reply + if http_request then + local src = getstring(f_ip_src().value) + local dst = getstring(f_ip_dst().value) + + http_table = processResponse(http_table, "requests", src, dst) + elseif http_reply then + local dst = getstring(f_ip_src().value) + local src = getstring(f_ip_dst().value) + + http_table = processResponse(http_table, "replies", src, dst) + end + + return http_table +end + +--############################################ + +local function httpReqRepRatio() + -- Declare the window we will use + local tw = TextWindow.new("HTTP Request/Reply Ratio") + + local http_table = {} + + local tap = Listener.new(); + + local function removeListener() + -- This way we remove the listener that otherwise will remain running indefinitely + tap:remove(); + end + + -- We tell the window to call the remove() function when closed + tw:set_atclose(removeListener) + + -- This function will be called once for each packet + function tap.packet(pinfo,tvb) + http_table = processPackets(pinfo,tvb, http_table) + end + + -- This function will be called once every few seconds to update our window + function tap.draw(t) + tw:clear() + + for flow in pairs(http_table) do + local requests = http_table[flow]["requests"] + local replies = http_table[flow]["replies"] + local ratio = 0 + local danger = "" + + if replies == 0 then + ratio = 0 + else + ratio = requests/replies + end + + if ratio ~= 1 then + danger = "-- DANGER: RATIO NOT 1 --\n" + end + + tw:append(danger .. flow .. ":\n\tRatio: " .. (ratio) .. "\n\tRequests: " .. requests .. "\n\tReplies: " .. replies .. "\n\n"); + end + end + + -- This function will be called whenever a reset is needed + -- e.g. when reloading the capture file + function tap.reset() + tw:clear() + http_table = {} + end + + -- Ensure that all existing packets are processed. + retap_packets() +end + +-- Register the menu Entry +register_menu("Sharkfest/HTTP Request-Reply Ratio", httpReqRepRatio, MENU_TOOLS_UNSORTED)
\ No newline at end of file diff --git a/wireshark/sharkfest_scripts/tcp_no_data_exchanged.lua b/wireshark/sharkfest_scripts/tcp_no_data_exchanged.lua new file mode 100644 index 000000000..7d9ac9839 --- /dev/null +++ b/wireshark/sharkfest_scripts/tcp_no_data_exchanged.lua @@ -0,0 +1,127 @@ + +-- +-- Sharkfest 2021 +-- +-- This is going to be an example of a lua script that can be written for cybersecurity reasons. +-- TCP No Data Exchanged: +-- The TCP No Data Exchanged is a really important script to check if flows are suspicious +-- Because usually, a typic TCP traffic, have some payload and it is not 0. Instead, in some attacks, +-- for example the TCP SYN Scan or SYN Flood, there is a lot of TCP traffic with no data. + +local f_tcp_traffic = Field.new("tcp") +local f_tcp_payload = Field.new("tcp.len") +local f_ip_src = Field.new("ip.src") +local f_ip_dst = Field.new("ip.dst") +local f_port_src = Field.new("tcp.srcport") +local f_port_dst = Field.new("tcp.dstport") +local f_conn_fin = Field.new("tcp.flags.fin") + +--############################################ + +local function getstring(finfo) + local ok, val = pcall(tostring, finfo) + if not ok then val = "(unknown)" end + return val +end + +--############################################ + +local function processResponse(tcp_table, src, src_port, dst, dst_port, payload) + local key = src .. ":" .. src_port .. "->" .. dst .. ":" .. dst_port + + -- Create the table entry if needed + if not tcp_table[key] then + local key2 = dst .. ":" .. dst_port .. "->" .. src .. ":" .. src_port + if not tcp_table[key2] then + tcp_table[key] = { + payload = 0, + fin = false + } + else + key = key2 + end + end + + -- Increase the stats + tcp_table[key]["payload"] = tcp_table[key]["payload"] + getstring(payload.value) + + if getstring(f_conn_fin().value) == true then + tcp_table[key]["fin"] = true + end + + return tcp_table +end + +--############################################ + +local function processPackets(pinfo,tvb, tcp_table) + -- Call the function that extracts the field + local tcp_traffic = f_tcp_traffic() + local tcp_payload = f_tcp_payload() + + --Check if there is an HTTP request or reply + if tcp_traffic then + local src = getstring(f_ip_src().value) + local dst = getstring(f_ip_dst().value) + local src_port = getstring(f_port_src().value) + local dst_port = getstring(f_port_dst().value) + + tcp_table = processResponse(tcp_table, src, src_port, dst, dst_port, tcp_payload) + end + + return tcp_table +end + +--############################################ + +local function tcpPayload() + -- Declare the window we will use + local tw = TextWindow.new("TCP No Data Exchanged") + + local tcp_table = {} + + local tap = Listener.new(); + + local function removeListener() + -- This way we remove the listener that otherwise will remain running indefinitely + tap:remove(); + end + + -- We tell the window to call the remove() function when closed + tw:set_atclose(removeListener) + + -- This function will be called once for each packet + function tap.packet(pinfo,tvb) + tcp_table = processPackets(pinfo,tvb, tcp_table) + end + + -- This function will be called once every few seconds to update our window + function tap.draw(t) + tw:clear() + + for flow in pairs(tcp_table) do + local payload = tcp_table[flow]["payload"] + local fin = tcp_table[flow]["fin"] + local danger = "" + + if tonumber(payload) == 0 then + danger = "-- DANGER: NO DATA EXCHANGED FOR THIS FLOW --\n" + end + + tw:append(danger .. flow .. ":\n\tPayload: " .. payload .. "\n\tFlow Ended: " .. tostring(fin) .. "\n\n"); + end + end + + -- This function will be called whenever a reset is needed + -- e.g. when reloading the capture file + function tap.reset() + tw:clear() + tcp_table = {} + end + + -- Ensure that all existing packets are processed. + retap_packets() +end + +-- Register the menu Entry +register_menu("Sharkfest/TCP No Data Exchanged", tcpPayload, MENU_TOOLS_UNSORTED)
\ No newline at end of file |