0

Im working on a script to get a list of users failed to access to the system

#!/bin/bash

#root auth
if [[ $UID != 0 ]];then 
echo -e "\e[31mPor favor corra este script como usuario root\e[0m"
exit 1
fi

AUTHLOG=/var/log/auth.log

if [[ -n $1 ]];
then
  AUTHLOG=$1
  echo Using Log file : $AUTHLOG
fi

# Collect the failed login attempts
FAILED_LOG=/tmp/failed.$$.log
egrep "Failed pass" $AUTHLOG > $FAILED_LOG 

# extract the users who failed
failed_users=$(cat $FAILED_LOG | awk '{ print $(NF-5) }' | sort | uniq)

# extract the IP Addresses of successful and failed login attempts
failed_ip_list="$(egrep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" $FAILED_LOG | sort | uniq)"

# Print the heading
printf "%-10s|%-10s|%-10s|%-15s|%-15s|%s\n" "Status" "User" "Attempts" "IP address" "Host" "Time range"

# Loop through IPs and Users who failed.

while read ip $failed_ip_list;
do
  while read user $failed_users;
    do
    # Count failed login attempts by this user from this IP
    attempts=`grep $ip $FAILED_LOG | grep " $user " | wc -l`

    if [ $attempts -ne 0 ]
    then
      first_time=`grep $ip $FAILED_LOG | grep " $user " | head -1 | cut -c-16`
      time="$first_time"
      if [ $attempts -gt 1 ]
      then
        last_time=`grep $ip $FAILED_LOG | grep " $user " | tail -1 | cut -c-16`
        time="$first_time -> $last_time"
      fi
      HOST=$(host $ip 8.8.8.8 | tail -1 | awk '{ print $NF }' )
      printf "%-10s|%-10s|%-10s|%-15s|%-15s|%-s\n" "Failed" "$user" "$attempts" "$ip"  "$HOST" "$time";
    fi
  done
done

rm -f $FAILED_LOG

I need to use while, but its nort working as expected because the promtp is giving me nothing in return. Im new to bash, so im learning.

My idea is to read the words "ip" and "user" to extrac the lines with each IP address and user combination. If the number of attempts for this IP/User combination is > 0, the time of the first occurrence is extracted with grep, head, and cut. If the number of attempts is > 1, then the last time is extracted using tail instead of head.

any thoughts of how can I accomplish that?

thanks!

EDIT: running set -x

+ [[ 0 != 0 ]]
+ AUTHLOG=/var/log/auth.log
+ [[ -n '' ]]
+ FAILED_LOG=/tmp/failed.2297.log
+ egrep 'Failed pass' /var/log/auth.log
++ uniq
++ sort
++ awk '{ print $(NF-5) }'
++ cat /tmp/failed.2297.log
+ failed_users=root
++ uniq
++ sort
++ egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' /tmp/failed.2297.log
+ failed_ip_list=192.168.0.185
+ printf '%-10s|%-10s|%-10s|%-15s|%-15s|%s\n' Status User Attempts 'IP address' Host 'Time range'
Status    |User      |Attempts  |IP address     |Host           |Time range
+ read -r ip
^C
  • 1
    There's much more code here than is ideal for a [mre]. Can you find the individual piece of your script that doesn't work as-intended and remove everything else? – Charles Duffy May 23 '21 at 23:47
  • 1
    ...using `set -x` (enabling line-by-line tracing) is helpful towards that end, particularly if you set `PS4=':$LINENO+'` to log the line number next to each piece of trace. – Charles Duffy May 23 '21 at 23:47
  • 1
    The grep failing because the script isn't run with enough permissions to read `auth.log` is pretty clear on its face, no? – Charles Duffy May 24 '21 at 00:14
  • the script is been running as root (its one of the validations that are ah te top of the script) – Marie Gutierrez May 24 '21 at 00:17
  • 1
    The other thing is that `while read ip $failed_ip_list` is just wrong. `failed_ip_list` doesn't do anything useful there. See [BashFAQ #1](https://mywiki.wooledge.org/BashFAQ/001) for details on correctly implementing a `while read` loop. – Charles Duffy May 24 '21 at 13:02
  • (I do see that you've replaced the log of a run with appropriate permissions). – Charles Duffy May 24 '21 at 13:12
  • ...so, per BashFAQ #1, instead of storing `failed_ip_list` in a variable, make it a process substitution after the `done`. That is: `while IFS= read -r ip; do ...; done < <(egrep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" $FAILED_LOG | sort -u)` – Charles Duffy May 24 '21 at 13:13
  • That said, an O(n^2) loop is not a great design from an efficiency perspective. It'd be a _lot_ faster to do all your analysis in a single pass; if the list of users and IPs will fit in memory, that's something an awk script should be able to do all at once. – Charles Duffy May 24 '21 at 13:15

0 Answers0