Experiment : log all SSH login attempts

A few weeks ago, while checking my server's logs, a thought crossed my mind: "How many people actually try to access a server when it's exposed to the public? And when they do, what usernames and passwords do they typically try?" It's one thing to hear about brute-force attacks and random login attempts, but another thing entirely to see it firsthand. So, I decided to run a little experiment. What if I tracked every SSH login attempt on an exposed server?

Before I dive into the technical details, a word of caution: Logging SSH passwords is discouraged due to the obvious security risks. This experiment was strictly for educational purposes, and I used a custom PAM (Pluggable Authentication Modules) module to capture these attempts.

Here's a way to do this on a AWS Linux system :

  1. Install the necessary tools:

     sudo yum install pam-devel gcc
    
  2. Create a custom PAM module:

    Make a file named spy.c:

     #include <security/pam_modules.h>
     #include <security/pam_ext.h>
     #include <security/pam_appl.h>
     #include <stdio.h>
     #include <time.h>
     #include <sys/socket.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
    
     PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
         const char *user = NULL;
         const char *pass = NULL;
         const char *rhost = NULL;
         char timebuf[80];
         time_t rawtime;
         struct tm *info;
    
         pam_get_user(pamh, &user, NULL);
         pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL);
         pam_get_item(pamh, PAM_RHOST, (const void**)&rhost);
    
         time(&rawtime);
         info = localtime(&rawtime);
         strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", info);
    
         int auth_status = pam_authenticate(pamh, 0);
         const char *status_msg = (auth_status == PAM_SUCCESS) ? "SUCCESS" : "FAILURE";
    
         FILE *log = fopen("/var/log/spy_diary.log", "a+");
         if (log) {
             fprintf(log, "Timestamp: %s, Remote Host: %s, User: %s, Password: %s, Status: %s\n", timebuf, rhost, user, pass, status_msg);
             fclose(log);
         }
    
         return auth_status;
     }
    
     PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) {
         return PAM_SUCCESS;
     }
    
  3. Compile the custom PAM module:

     gcc -fPIC -fno-stack-protector -c spy.c
     sudo mkdir /lib/movies
     sudo ld -x --shared -o /lib/movies/spy.so spy.o
    
  4. Update PAM configuration:

    Edit the SSH PAM configuration:

     sudo nano /etc/pam.d/sshd
    

    Add the following line at the top:

     auth       required     /lib/movies/spy.so
    
  5. To enable Password authentication on your server please follow this tutorial here.

  6. Restart SSH:

     sudo systemctl restart sshd
    
  7. Test: peaking image

    Try to SSH into the system. Even if the login fails, the username and password will be logged in /var/log/spy_diary.log with Timestamp and IP address of the user. Use the below command to see the logs.

     cat /var/log/spy_diary.log
    

I left this setup be for a week and my logs were disturbingly huge in size. I will write another article with my findings soon.

⚠️ Important Warnings:

  • This will log all passwords in plain text. You should not use this in any production or sensitive environment.
  • Remember to remove or disable this module when you're done with your testing to ensure no passwords continue to be logged.
  • Ensure the log file /var/log/spy_diary.log is secured and not readable by unauthorized users. Consider regularly deleting its contents.
  • Always be cautious when implementing something that can expose sensitive information.