Skip to content

Commit

Permalink
more work on the telnet detection feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mmguero committed Apr 13, 2020
1 parent b643c44 commit d921cf9
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 23 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -257,6 +257,7 @@ Malcolm uses [Zeek](https://docs.zeek.org/en/stable/script-reference/proto-analy
|Secure Sockets Layer (SSL) / Transport Layer Security (TLS)|[🔗](https://en.wikipedia.org/wiki/Transport_Layer_Security)|[🔗](https://tools.ietf.org/html/rfc5246)|[](https://github.com/aol/moloch/blob/master/capture/parsers/socks.c)|[](https://docs.zeek.org/en/stable/scripts/base/protocols/ssl/main.zeek.html#type-SSL::Info)|
|Syslog|[🔗](https://en.wikipedia.org/wiki/Syslog)|[🔗](https://tools.ietf.org/html/rfc5424)|[](https://github.com/aol/moloch/blob/master/capture/parsers/tls.c)|[](https://docs.zeek.org/en/stable/scripts/base/protocols/syslog/main.zeek.html#type-Syslog::Info)|
|Tabular Data Stream|[🔗](https://en.wikipedia.org/wiki/Tabular_Data_Stream)|[🔗](https://www.freetds.org/tds.html) [🔗](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/b46a581a-39de-4745-b076-ec4dbb7d13ec)|[](https://github.com/aol/moloch/blob/master/capture/parsers/tds.c)|[](https://github.com/amzn/zeek-plugin-tds/blob/master/scripts/main.zeek)|
|Telnet / remote shell (rsh) / remote login (rlogin)|[🔗](https://en.wikipedia.org/wiki/Telnet)[🔗](https://en.wikipedia.org/wiki/Berkeley_r-commands)|[🔗](https://tools.ietf.org/html/rfc854)[🔗](https://tools.ietf.org/html/rfc1282)|[](https://github.com/aol/moloch/blob/master/capture/parsers/misc.c#L336)|[](https://docs.zeek.org/en/current/scripts/base/bif/plugins/Zeek_Login.events.bif.zeek.html)|
|various tunnel protocols (e.g., GTP, GRE, Teredo, AYIYA, IP-in-IP, etc.)|[🔗](https://en.wikipedia.org/wiki/Tunneling_protocol)||[](https://github.com/aol/moloch/blob/master/capture/packet.c)|[](https://docs.zeek.org/en/stable/scripts/base/frameworks/tunnels/main.zeek.html#type-Tunnel::Info)|

Additionally, Zeek is able to detect and, where possible, log the type, vendor and version of [various](https://docs.zeek.org/en/stable/scripts/base/frameworks/software/main.zeek.html#type-Software::Type) other [software protocols](https://en.wikipedia.org/wiki/Application_layer).
Expand Down
30 changes: 30 additions & 0 deletions logstash/pipelines/zeek/11_zeek_logs.conf
Expand Up @@ -2316,6 +2316,36 @@ filter {
}
}

} else if ([source] == "telnet") {
#############################################################################################################################
# telnet.log
# custom telnet.log module (rudimentary, still a lot to be improved since the analyzers are pretty confused)

dissect {
id => "dissect_zeek_telnet"
# zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP
mapping => {
"[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][success]} %{[zeek_cols][confused]} %{[zeek_cols][user]} %{[zeek_cols][client_user]} %{[zeek_cols][password]}"
}
}
if ("_dissectfailure" in [tags]) {
mutate {
id => "mutate_split_zeek_telnet"
# zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP
split => { "[message]" => " " }
}
ruby {
id => "ruby_zip_zeek_telnet"
init => "$zeek_telnet_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'success', 'confused', 'user', 'client_user', 'password' ]"
code => "event.set('[zeek_cols]', $zeek_telnet_field_names.zip(event.get('[message]')).to_h)"
}
}

mutate {
id => "mutate_add_fields_zeek_telnet"
add_field => { "[zeek_cols][service]" => "telnet" }
}

} else if ([source] == "tunnel") {
#############################################################################################################################
# tunnel.log
Expand Down
8 changes: 7 additions & 1 deletion moloch/wise/source.zeeklogs.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion shared/bin/zeek_install_plugins.sh
Expand Up @@ -73,8 +73,8 @@ ZKG_GITHUB_URLS=(
https://github.com/amzn/zeek-plugin-profinet
https://github.com/amzn/zeek-plugin-s7comm
https://github.com/amzn/zeek-plugin-tds
https://github.com/corelight/bro-community-id
https://github.com/corelight/bro-xor-exe-plugin
https://github.com/corelight/zeek-community-id
https://github.com/cybera/zeek-sniffpass
https://github.com/lexibrent/zeek-EternalSafety
https://github.com/mitre-attack/bzar
Expand Down
223 changes: 202 additions & 21 deletions zeek/config/telnet.zeek
@@ -1,37 +1,217 @@
global telnet_ports: set[port] = { 23/tcp } &redef;
module Telnet;

event zeek_init()
{
Analyzer::register_for_ports(Analyzer::ANALYZER_TELNET, telnet_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_RSH, telnet_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_RLOGIN, telnet_ports);
# log telnet, rlogin, and rsh events to telnet.log

export {

redef enum Log::ID += {
## The telnet protocol logging stream identifier
Log_TELNET
};

type Info : record {
## Time the event occurred
ts : time &log;
## Unique ID for the connection
uid : string &log;
## The connection's 4-tuple of endpoint addresses/port
id : conn_id &log;

## login_success event was seen (successful login)
success : bool &log &default = F;
## login_confused event was seen (successful login)
confused : bool &log &default = F;
## username given for login attempt
user : string &log &optional;
## client_user given for login attempt (empty for telnet, set for rlogin)
client_user : string &log &optional;
## password given for login attempt
password : string &log &optional;

## whether or not a line has been written to telnet.log
logged : bool &default = F;
};

## Event that can be handled to access the :zeek:type:`Telnet::Info`
## record as it is sent on to the logging framework.
global log_telnet : event(rec : Info);
}

# Add the state tracking information variable to the connection record
redef record connection += {
telnet : Info &optional;
};

###############################################
# constants borrowed from the old Bro 1.5 login.bro required to make some of the telnet/rlogin/rsh events work correctly
# see https://github.com/zeek/zeek/blob/release/1.5/policy/login.bro#L178
# https://github.com/reservoirlabs/brorefguide/blob/master/analysis.texi#L3850

redef skip_authentication = { "WELCOME TO THE BERKELEY PUBLIC LIBRARY", };

redef direct_login_prompts = { "TERMINAL?", };

redef login_prompts = {
"Login:",
"login:",
"Name:",
"Username:",
"User:",
"Member Name",
"User Access Verification",
"Cisco Systems Console",
direct_login_prompts
};

redef login_non_failure_msgs = {
"Failures",
"failures", # probably is "<n> failures since last login"
"failure since last successful login",
"failures since last successful login",
};

redef login_non_failure_msgs = {
"Failures",
"failures", # probably is "<n> failures since last login"
"failure since last successful login",
"failures since last successful login",
} &redef;

redef login_failure_msgs = {
"invalid",
"Invalid",
"incorrect",
"Incorrect",
"failure",
"Failure",
# "Unable to authenticate",
# "unable to authenticate",
"User authorization failure",
"Login failed",
"INVALID",
"Sorry.",
"Sorry,",
};

const router_prompts: set[string] &redef;

redef login_success_msgs = {
"Last login",
"Last successful login",
"Last successful login",
"checking for disk quotas",
"unsuccessful login attempts",
"failure since last successful login",
"failures since last successful login",
router_prompts,
};

redef login_timeouts = {
"timeout",
"timed out",
"Timeout",
"Timed out",
"Error reading command input", # VMS
};
# end borrowed constants from Bro 1.5 login.bro
###############################################

# telnet, rlogin, rsh
const telnet_port = { 23/tcp };
const rlogin_port = { 513/tcp };
const rsh_port = { 514/tcp };
redef likely_server_ports += { telnet_port, rlogin_port, rsh_port };

# set_telnet_session - if has not yet been registered in the connection, instantiate
# the Info record and assign in c$telnet
function set_telnet_session(c : connection) {
if ( ! c?$telnet ) {
local s : Info = [$ts = network_time(), $uid = c$uid, $id = c$id];
c$telnet = s;
add c$service["telnet"];
}
}

event login_confused(c: connection, msg: string, line: string)
{
# telnet_message - log to telnet.log
function telnet_message(s : Info) {

# strip some values that can happen in a "confused" state that aren't really valid values
if (( s?$user ) && (( s$user == "" ) || ( s$user == "<none>" ) || ( s$user == "<timeout>" )))
delete s$user;
if (( s?$client_user ) && (( s$client_user == "" ) || ( s$client_user == "<none>" ) || ( s$client_user == "<timeout>" )))
delete s$client_user;
if (( s?$password ) && (( s$password == "" ) || ( s$password == "<none>" ) || ( s$password == "<timeout>" )))
delete s$password;

s$ts = network_time();
Log::write(Telnet::Log_TELNET, s);
s$logged = T;
}

# create log stream for telnet.log and register telnet, rlogin, and rsh analyzers
event zeek_init() &priority = 5 {
Log::create_stream(Telnet::Log_TELNET, [$columns = Info, $ev = log_telnet, $path = "telnet"]);
Analyzer::register_for_ports(Analyzer::ANALYZER_TELNET, telnet_port);
Analyzer::register_for_ports(Analyzer::ANALYZER_RLOGIN, rlogin_port);
Analyzer::register_for_ports(Analyzer::ANALYZER_RSH, rsh_port);
}

# login_confused - Generated when tracking of Telnet/Rlogin authentication failed
# https://docs.zeek.org/en/current/scripts/base/bif/plugins/Zeek_Login.events.bif.zeek.html#id-login_confused
event login_confused(c : connection, msg : string, line : string) &priority = 5 {
# print "login_confused", msg, line;
if (|c$service| == 0) add c$service["telnet"];

set_telnet_session(c);

c$telnet$confused = T;
}

event login_failure(c: connection, user: string, client_user: string, password: string, line: string)
{
# login_failure - Generated when tracking of Telnet/Rlogin authentication failed
# https://docs.zeek.org/en/current/scripts/base/bif/plugins/Zeek_Login.events.bif.zeek.html#id-login_failure
event login_failure(c : connection, user : string, client_user : string, password : string, line : string) &priority = 5 {
# print "login_failure", user, client_user, password, line;
if (|c$service| == 0) add c$service["telnet"];
}

event login_prompt(c: connection, prompt: string)
{
# print "login_prompt", prompt;
if (|c$service| == 0) add c$service["telnet"];
set_telnet_session(c);

if (c$telnet$user == "")
c$telnet$user = user;
if (c$telnet$client_user == "")
c$telnet$client_user = client_user;
if (c$telnet$password == "")
c$telnet$password = password;

telnet_message(c$telnet);
}

event login_success(c: connection, user: string, client_user: string, password: string, line: string)
{
# login_success - Generated for successful Telnet/Rlogin logins
# https://docs.zeek.org/en/current/scripts/base/bif/plugins/Zeek_Login.events.bif.zeek.html#id-login_success
event login_success(c : connection, user : string, client_user : string, password : string, line : string) &priority = 5 {
# print "login_success", user, client_user, password, line;
if (|c$service| == 0) add c$service["telnet"];

set_telnet_session(c);

c$telnet$success = T;
c$telnet$user = user;
c$telnet$client_user = client_user;
c$telnet$password = password;

telnet_message(c$telnet);
}

event connection_state_remove(c : connection) &priority = -5 {
if (c?$telnet) {

if ( c$telnet$logged == F) {
telnet_message(c$telnet);
}

delete c$telnet;
}
}

# for file in /host/telnet/*; do cd /tmp; mkdir -p /host/logs/"$(basename "$file")"; /bin/rm -f /host/logs/"$(basename "$file")"/*; cd /host/logs/"$(basename "$file")"; zeek -r "$file" local /host/telnet.zeek > debug_output.txt; cd /tmp; done
# for testing:
# for file in /host/telnet/*; do cd /tmp; mkdir -p /host/logs/"$(basename "$file")"; /bin/rm -f /host/logs/"$(basename "$file")"/*; cd /host/logs/"$(basename "$file")"; zeek -r "$file" local > debug_output.txt; cd /tmp; done

# event activating_encryption(c: connection) { print "activating_encryption"; }
# event authentication_accepted(name: string, c: connection) { print "authentication_accepted", name; }
# event authentication_rejected(name: string, c: connection) { print "authentication_rejected", name; }
Expand All @@ -46,3 +226,4 @@ event login_success(c: connection, user: string, client_user: string, password:
# event login_terminal(c: connection, terminal: string) { print "login_terminal", terminal; }
# event rsh_reply(c: connection, client_user: string, server_user: string, line: string) { print "rsh_reply", client_user, server_user, line; }
# event rsh_request(c: connection, client_user: string, server_user: string, line: string; new_session: bool) { print "rsh_request", client_user, server_user, line, new_session; }

0 comments on commit d921cf9

Please sign in to comment.