mirror of
https://github.com/zeek/zeek.git
synced 2025-10-11 02:58:20 +00:00
Updates for SSH scripts.
This commit is contained in:
parent
9a06cece67
commit
9c2273b7a7
6 changed files with 237 additions and 141 deletions
79
scripts/policy/protocols/ssh/detect-bruteforcing.bro
Normal file
79
scripts/policy/protocols/ssh/detect-bruteforcing.bro
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
module SSH;
|
||||
|
||||
export {
|
||||
redef enum Notice::Type += {
|
||||
## Indicates that a host has been identified as crossing the
|
||||
## :bro:id:`password_guesses_limit` threshold with heuristically
|
||||
## determined failed logins.
|
||||
Password_Guessing,
|
||||
## Indicates that a host previously identified as a "password guesser"
|
||||
## has now had a heuristically successful login attempt.
|
||||
Login_By_Password_Guesser,
|
||||
};
|
||||
|
||||
## The number of failed SSH connections before a host is designated as
|
||||
## guessing passwords.
|
||||
const password_guesses_limit = 30 &redef;
|
||||
|
||||
## The amount of time to remember presumed non-successful logins to build
|
||||
## model of a password guesser.
|
||||
const guessing_timeout = 30 mins &redef;
|
||||
|
||||
## This value can be used to exclude hosts or entire networks from being
|
||||
## tracked as potential "guessers". There are cases where the success
|
||||
## heuristic fails and this acts as the whitelist. The index represents
|
||||
## client subnets and the yield value represents server subnets.
|
||||
const ignore_guessers: table[subnet] of subnet &redef;
|
||||
|
||||
## Keeps count of how many rejections a host has had.
|
||||
global password_rejections: table[addr] of TrackCount
|
||||
&write_expire=guessing_timeout
|
||||
&synchronized;
|
||||
|
||||
## Keeps track of hosts identified as guessing passwords.
|
||||
global password_guessers: set[addr] &read_expire=guessing_timeout+1hr &synchronized;
|
||||
}
|
||||
|
||||
event SSH::heuristic_successful_login(c: connection)
|
||||
{
|
||||
local id = c$id;
|
||||
|
||||
# TODO: this should be migrated to the metrics framework.
|
||||
if ( id$orig_h in password_rejections &&
|
||||
password_rejections[id$orig_h]$n > password_guesses_limit &&
|
||||
id$orig_h !in password_guessers )
|
||||
{
|
||||
add password_guessers[id$orig_h];
|
||||
NOTICE([$note=Login_By_Password_Guesser,
|
||||
$conn=c,
|
||||
$n=password_rejections[id$orig_h]$n,
|
||||
$msg=fmt("Successful SSH login by password guesser %s", id$orig_h),
|
||||
$sub=fmt("%d failed logins", password_rejections[id$orig_h]$n)]);
|
||||
}
|
||||
}
|
||||
|
||||
event SSH::heuristic_failed_login(c: connection)
|
||||
{
|
||||
local id = c$id;
|
||||
|
||||
# presumed failure
|
||||
if ( id$orig_h !in password_rejections )
|
||||
password_rejections[id$orig_h] = new_track_count();
|
||||
|
||||
# Track the number of rejections
|
||||
# TODO: this should be migrated to the metrics framework.
|
||||
if ( ! (id$orig_h in ignore_guessers &&
|
||||
id$resp_h in ignore_guessers[id$orig_h]) )
|
||||
++password_rejections[id$orig_h]$n;
|
||||
|
||||
if ( default_check_threshold(password_rejections[id$orig_h]) )
|
||||
{
|
||||
add password_guessers[id$orig_h];
|
||||
NOTICE([$note=Password_Guessing,
|
||||
$conn=c,
|
||||
$msg=fmt("SSH password guessing by %s", id$orig_h),
|
||||
$sub=fmt("%d apparently failed logins", password_rejections[id$orig_h]$n),
|
||||
$n=password_rejections[id$orig_h]$n]);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue