Re: PATCH for sshd
Markus Lude <[email protected]> Mon, 12 Sep 2016 02:00:43 +0200
| Newsgroups | gmane.comp.log.logwatch.devel |
|---|---|
| Message-ID | <[email protected]> |
On Sun, Sep 11, 2016 at 08:59:07PM +1000, Frank Crawford wrote:
> Clean up a lot of messages that are now seen in recent sshd including a
> fix for the recent update for handling SSH_DISCONNECTS codes, handling
> of the '[preauth]' tag that has started appearing and added a new
> report on failed negotiations.
>
> It also removed the old BadRSA report as nothing was setting the
> variables.
>
> Again, these are based on the latest version with Fedora 24.
Some comments below
> Regards
> Frank
> diff --git a/scripts/services/sshd b/scripts/services/sshd
> index a7edb41..27f024b 100755
> --- a/scripts/services/sshd
> +++ b/scripts/services/sshd
> @@ -201,6 +201,7 @@ my %BadLogins = ();
> my %NoRevMap = ();
> my %RefusedConnections = ();
> my %RefusedAuthentication = ();
> +my %NegotiationFailed = ();
> my %DisconnectReceived = ();
> my %RootLogin = ();
> my %PamReleaseFail = ();
> @@ -223,7 +224,6 @@ my %MisMatch = ();
> my %KrbAutFail = ();
> my %KrbAutErr = ();
> my %KrbErr = ();
> -my @BadRSA = ();
> my @Scanned = ();
> my %OtherList = ();
> my %ChmodErr = ();
> @@ -273,7 +273,7 @@ while (defined(my $ThisLine = <STDIN>)) {
> ($ThisLine =~ m/^channel_lookup: -?\d+: bad id/) or
> ($ThisLine =~ m/^error: channel \d+: chan_read_failed for istate/) or
> # Result of setting PermitRootLogin to forced-commands-only
> - ($ThisLine =~ m/^Root login accepted for forced command.$/) or
> + ($ThisLine =~ m/^Root login accepted for forced command.( \[preauth])?$/) or
I think a backslash is missing there after preauth: \[preauth\]
The dot looks strange too. Is this a real dot or a wildcard for any
character there? Is it before or after [preauth]? Maybe show some
example log entry.
> # usually followed by a session opened for user
> ($ThisLine =~ m/^pam_krb5\[\d+\]: authentication succeeds for /) or
> ($ThisLine =~ m/^nss_ldap: reconnect/) or
> @@ -283,11 +283,13 @@ while (defined(my $ThisLine = <STDIN>)) {
> ($ThisLine =~ m/^\(pam_unix\) .*/) or
> ($ThisLine =~ m/^pam_unix\(.*:.*\)/) or
> ($ThisLine =~ m/^pam_unix_auth:/) or
> + ($ThisLine =~ m/^pam_sepermit\(.*:.*\)/) or
> ($ThisLine =~ /pam_krb5: authentication succeeds for `([^ ]*)'/) or
> ($ThisLine =~ /pam_succeed_if\(.*:.*\): error retrieving information about user [a-zA-Z]*/ ) or
> ($ThisLine =~ /pam_winbind\(sshd:account\): user .* granted access/) or
> ($ThisLine =~ /pam_winbind\(sshd:account\): user .* OK/) or
> ($ThisLine =~ /pam_systemd\(sshd:session\): Moving/) or
> + ($ThisLine =~ /pam_systemd\(sshd:session\): .*: Connection reset by peer/) or
> ($ThisLine =~ /PAM \d+ more authentication failures?;/) or
> ($ThisLine =~ /^PAM service\(sshd\) ignoring max retries;/) or
> ($ThisLine =~ /^Failed keyboard-interactive for <invalid username> from/ ) or
> @@ -297,7 +299,8 @@ while (defined(my $ThisLine = <STDIN>)) {
> ($ThisLine =~ /Starting session: (forced-command|subsystem|shell|command)/ ) or
> ($ThisLine =~ /Found matching \w+ key:/ ) or
> ($ThisLine =~ /User child is on pid \d/ ) or
> - ($ThisLine =~ /Nasty PTR record .* is set up for [\da-fA-F.:]+, ignoring/)
> + ($ThisLine =~ /Nasty PTR record .* is set up for [\da-fA-F.:]+, ignoring/) or
> + ($ThisLine =~ /Disconnected from [\da-fA-F.:]* port \d*/ )
> ) {
> # Ignore these
> } elsif ( my ($Method,$User,$Host,$Port,$Key) = ($ThisLine =~ /^Accepted (\S+) for ((?:invalid user )?\S+) from ([\d\.:a-f]+) port (\d+) ssh[12](?:: (\w+))?/) ) {
> @@ -315,6 +318,10 @@ while (defined(my $ThisLine = <STDIN>)) {
> $IllegalUsers{$Host}{$User}++;
> } elsif ( my ($User) = ( $ThisLine =~ /Disconnecting: Too many authentication failures for ([^ ]+)/)) {
> $TooManyFailures{$User}++;
> + } elsif ( my ($User) = ( $ThisLine =~ /error: maximum authentication attempts exceeded for ([^ ]+) from [^ ]+ port \d+ ssh2 \[preauth]/)) {
> + $TooManyFailures{$User}++;
> + } elsif ( $ThisLine =~ /Disconnecting: Too many authentication failures \[preauth]/ ) {
> + # Ignore these - should be covered by other messages
> } elsif ( $ThisLine =~ m/^(fatal: )?Did not receive ident(ification)? string from (.+)/ ) { # ssh/openssh
> my $name = LookupIP($3);
> $NoIdent{$name}++;
> @@ -329,6 +336,7 @@ while (defined(my $ThisLine = <STDIN>)) {
> ($ThisLine =~ m/^fatal: Write failed: Network is unreachable/ ) or
> ($ThisLine =~ m/^fatal: Write failed: Broken pipe/) or
> ($ThisLine =~ m/^fatal: Write failed: Connection reset by peer/) or
> + ($ThisLine =~ m/^Connection reset by [^ ]+/) or
simpler and probably the same matching with m/^Connection reset by /
> ($ThisLine =~ m/^channel \d+: open failed: (?:connect failed: Channel open failed\.|administratively prohibited: open failed)/) or
> ($ThisLine =~ m/^session_input_channel_req: no session \d+ req window-change/) or
> ($ThisLine =~ m/^error: chan_shutdown_read failed for .+/)
> @@ -387,9 +395,20 @@ while (defined(my $ThisLine = <STDIN>)) {
> $RefusedConnections{$1}++;
> } elsif ( my ($Reason) = ($ThisLine =~ /^Authentication refused: (.*)$/ ) ) {
> $RefusedAuthentication{$Reason}++;
> - } elsif ( my ($Host,$Reason) = ($ThisLine =~ /^Received disconnect from ([^ ]*)(?: port [^ ]*)?: (.*)$/)) {
> + } elsif ( my ($Host,$Port,$Reason,$Offer) = ($ThisLine =~ /^fatal: Unable to negotiate with ([^ ]+)( port \d+)?: (.*)\. Their offer: (.*) \[preauth]$/) ) {
> + $NegotiationFailed{$Reason}{$Host}{$Offer}++;
> + } elsif ( my ($Reason,$Host,$Offer) = ($ThisLine =~ /^(Protocol major versions differ) for ([^ ]+): (.*)$/) ) {
> + $NegotiationFailed{$Reason}{$Host}{$Offer}++;
> + } elsif ( my ($Prio,$Host,$Port,$Code,$Reason) = ($ThisLine =~ /^(error: )?Received disconnect from ([^ ]*)( port \d+)?: ?(\d+): (.*) \[preauth]$/)) {
> + if ($Code == 11) {
> + # Reason 11 (SSH_DISCONNECT_BY_APPLICATION) in [preauth] sounds suspicious
> + $DisconnectReceived{"$Reason [preauth]"}{$Host}++;
please expand tabs to spaces
> + } else {
> + $DisconnectReceived{$Reason}{$Host}++;
same here
> + }
> + } elsif ( my ($Prio,$Host,$Port,$Code,$Reason) = ($ThisLine =~ /^(error: )?Received disconnect from ([^ ]*)( port \d+)?: ?(\d+): (.*)$/)) {
> # Reason 11 (SSH_DISCONNECT_BY_APPLICATION) is expected, and logged at severity level INFO
> - if ($Reason != 11) {$DisconnectReceived{$Reason}{$Host}++;}
> + if ($Code != 11) {$DisconnectReceived{$Reason}{$Host}++;}
> } elsif ( my ($Host) = ($ThisLine =~ /^ROOT LOGIN REFUSED FROM ([^ ]*)$/)) {
> $RootLogin{$Host}++;
> } elsif ( my ($Error) = ($ThisLine =~ /^Cannot release PAM authentication\[\d\]: (.*)$/)) {
> @@ -440,6 +459,9 @@ while (defined(my $ThisLine = <STDIN>)) {
> } elsif ( my (undef,$User,$Host) = ($ThisLine =~ m/^(Illegal|Invalid) user (.*) from ([^ ]+)/ )) {
> $PotentialIllegalUsers{$Host}{$User}++;
> } elsif ( my (undef,$User) = ($ThisLine =~ /^input_userauth_request: (illegal|invalid) user (.*)$/ )) {
> + if ($User =~ m/(.*) \[preauth]/) {
> + $User = $1;
and here
> + }
> $PotentialIllegalUsers{"undef"}{$User}++;
> } elsif (my ($File,$Perm,$Why) = ($ThisLine =~ /error: chmod (.*) (.*) failed: (.*)/)) {
> $ChmodErr{"$File,$Perm,$Why"}++;
> @@ -531,10 +553,35 @@ if ($Detail >= 10) {
> }
> }
>
> -if ($#BadRSA >= 0) {
> - print "\nReceived a bad response to RSA challenge from:\n";
> - foreach my $ThisOne (@BadRSA) {
> - print " $ThisOne\n";
> +if (keys %NegotiationFailed) {
> + print "\nNegotiation failed:\n";
> + foreach my $Reason (sort {$a cmp $b} keys %NegotiationFailed) {
> + my $Total = 0;
> + print " $Reason";
> + foreach my $Host (sort {$a cmp $b} keys %{$NegotiationFailed{$Reason}}) {
> + my $HostTotal = 0;
> + foreach my $Offer (sort {$a cmp $b} keys %{$NegotiationFailed{$Reason}{$Host}}) {
> + $HostTotal += $NegotiationFailed{$Reason}{$Host}{$Offer};
> + }
> + $Total += $HostTotal;
> + if ( $Detail > 0 ) {
> + my $plural = ($HostTotal > 1) ? "s" : "";
> + print "\n $Host: $HostTotal time$plural";
> + }
> + if ( $Detail > 5 ) {
> + foreach my $Offer (sort {$a cmp $b} keys %{$NegotiationFailed{$Reason}{$Host}}) {
> + my $tot = $NegotiationFailed{$Reason}{$Host}{$Offer};
> + my $plural = ($tot > 1) ? "s" : "";
> + print "\n $Offer: $tot time$plural";
> + }
> + }
and here in the lines above
> + }
> + if( $Detail > 0 ) {
> + print "\n";
> + } else {
> + my $plural = ($Total > 1) ? "s" : "";
and here
> + print ": $Total time$plural\n";
> + }
> }
> }
>
> @@ -685,7 +732,7 @@ if (keys %Users) {
> }
>
> if (keys %RefusedAuthentication) {
> - print "\n\nAuthentication refused:\n";
> + print "\nAuthentication refused:\n";
> foreach my $Reason (sort {$a cmp $b} keys %RefusedAuthentication) {
> print " $Reason : $RefusedAuthentication{$Reason} Time(s)\n";
> }
> @@ -715,7 +762,7 @@ if (keys %KrbErr) {
>
>
> if (keys %DisconnectReceived) {
> - print "\n\nReceived disconnect:\n";
> + print "\nReceived disconnect:\n";
> foreach my $Reason (sort {$a cmp $b} keys %DisconnectReceived) {
> my $Total = 0;
> print " $Reason";
------------------------------------------------------------------------------