Shell script to check login history in Linux


Shell Scripting

One of the roles of System and Linux Administrator is to monitor user login history so that they are aware of system activity. These are very important from security perspective to track the number of users who connect to any Linux server. You can use the commands from this script to track this successful and failed logins manually or use the script from this tutorial which will give you a summarised and detail output of all Linux login history.

 

Monitoring user logins to find intruders

Log files can be used to gather details about the state of the system and attacks on the system.

Suppose we have a system connected to the Internet with SSH enabled. Many attackers are trying to log in to the system. We need to design an intrusion detection system to identify users who fail their login attempts. Such attempts may be of a hacker using a dictionary attack. The script should generate a report with the following details:

User with successful attempts and that failed to log in

  • Number of attempts
  • IP address of the attacker
  • Host mapping for the IP address
  • Time when login attempts occurred

 

Log Files to check login attempts

Based on your distribution the log files to check login history will differ. On my RHEL/CentOS 7/8 Linux node these information are captured in /var/log/secure. But in some distribution this is captured in /var/log/auth.log

 

Shell script to check Linux Login History

Below is a sample shell script which will check successful and failed login attempts on Linux node using /var/log/secure.

#!/bin/bash
# Filename: intruder_detect.sh
# Description: Check Linux Login History
AUTHLOG=/var/log/secure

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 

# Collect the successful login attempts
SUCCESS_LOG=/tmp/success.$$.log
egrep "Accepted password|Accepted publickey|keyboard-interactive" $AUTHLOG > $SUCCESS_LOG

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

# extract the users who successfully logged in
success_users=$(cat $SUCCESS_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)"
success_ip_list="$(egrep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" $SUCCESS_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.

for ip in $failed_ip_list;
do
  for user in $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

for ip in $success_ip_list;
do
  for user in $success_users;
    do
    # Count successful login attempts by this user from this IP
    attempts=`grep $ip $SUCCESS_LOG | grep " $user " | wc -l`

    if [ $attempts -ne 0 ]
    then
      first_time=`grep $ip $SUCCESS_LOG | grep " $user " | head -1 | cut -c-16`
      time="$first_time"
      if [ $attempts -gt 1 ]
      then
        last_time=`grep $ip $SUCCESS_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" "Success" "$user" "$attempts" "$ip"  "$HOST" "$time";
    fi
  done
done

rm -f $FAILED_LOG
rm -f $SUCCESS_LOG

 

Give executable permission to the script

# chmod u+x /tmp/intruder_detect.sh

Execute the script

# /tmp/intruder_detect.sh
Status    |User      |Attempts  |IP address     |Host           |Time range
Failed    |root      |5         |192.168.0.102  |3(NXDOMAIN)    |Jan 11 20:44:04  -> Jan 11 20:50:17
Failed    |root      |2         |192.168.0.106  |3(NXDOMAIN)    |Jan 11 20:51:54  -> Jan 11 20:51:59
Success   |root      |1         |192.168.0.102  |3(NXDOMAIN)    |Jan 11 20:50:26
Success   |root      |2         |192.168.0.106  |3(NXDOMAIN)    |Jan 11 21:50:24  -> Jan 11 21:50:42

Based on these logs we can figure out that there were 5 failed login attempts from 192.168.0.102, 2 failed login attempts from 192.168.0.106
Similarly there were couple of successful login attempts from 192.168.0.102 and 192.168.0.106

 

How the script works?

  • The intruder_detect.sh script defaults to using /var/log/secure as input. Alternatively, we can provide a log file with a command-line argument.
  • The successful and failed logins are collected in a temporary file to reduce processing.
  • When a login attempt fails, SSH logs lines are similar to this:
sshd[3217]: Failed password for root from 192.168.0.102 port 53720 ssh2
  • When a login is successful, SSH logs lines are similar to this
sshd[4881]: Accepted password for root from 192.168.0.106 port 49920 ssh2
  • The script greps for the "Failed passw" string to get failed login attempt details and puts those lines in /tmp/failed.$$.log
  • The script greps for "Accepted password|Accepted publickey|keyboard-interactive" string to get successful login attempts and puts those lines in /tmp/success.$$.log
  • The $$ in the temporary filename will be automatically replaced by the script's PID
  • The next step is to extract the users who successfully logged in and who failed to login.
    The awk command extracts the fifth field from the end (the user name) and pipes that to sort and uniq to create a list of the users.
  • Next, the unique IP addresses are extracted with a regular expression and the egrep command.
    Nested for loops iterate through the IP address and users extracting 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.
  • This login attempt is then reported with the formatted printf command.
  • Finally, the temporary file is removed.

 

Conclusion

In this tutorial we learned how we can check login history of users in Linux and consolidate the output based on the data available from /var/log/secure. You could also setup audit to get the list of all login attempts from different Linux users.

Lastly I hope the steps from the article to check and monitor Linux login history was helpful. So, let me know your suggestions and feedback using the comment section.

References

I have used below external references for this tutorial guide
Script to check successful and failed login attempts in Linux

 

Deepak Prasad

Deepak Prasad

Deepak Prasad is the founder of GoLinuxCloud, bringing over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, Networking, and Security. His extensive experience spans development, DevOps, networking, and security, ensuring robust and efficient solutions for diverse projects.

Certifications and Credentials:

  • Certified Kubernetes Application Developer (CKAD)
  • Go Developer Certification
  • Linux Foundation Certified System Administrator (LFCS)
  • Certified Ethical Hacker (CEH)
  • Python Institute PCAP (Certified Associate in Python Programming)
You can connect with him on his LinkedIn profile and join his Facebook and LinkedIn page.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

5 thoughts on “Shell script to check login history in Linux”

    • Store printf content to a log file and run this script using cron. You can adjust the cron value based on your requirement. For example to run everyday at 8 AM use 0 8 * * *

      Reply
  1. The script works well but a lot of lines with “grep: Invalid back reference” may be some problem with the version of egrep ? I’m on a Centos 7 machine

    Reply
    • This is to perform a IP to hostname lookup. We are using Google’s DNS to perform the lookup. Since my lab is in private network, I am getting NXDOMAIN, but if you do a lookup of a public IP then you should get proper hostname value. Or you can also use your own DNS (if any) to perform hostname lookup

      Reply

Leave a Comment