Using Gource to Visualize SSH Attempts...Because Why Not?

This is way out of date now

The information in this post is so out-dated that I wonder why I'm keeping it around. I guess I'm a digital hoarder...

As with most endeavours related to the question "I wonder if I can do X?", this one started off on a day where I was very VERY bored.

The question "Can I use Gource to Visualize SSH Logs?" was quickly answered when I remembered Gource can take any logs that I can get to follow the custom format.

Custom Log Format
    If you want to use Gource with something other than the supported systems, there is a pipe ('|') delimited custom log format:

       timestamp - A unix timestamp of when the update occured.
       username  - The name of the user who made the update.
       type      - Single character for the update type - (A)dded, (M)odified or (D)eleted.
       file      - Path of the file updated.
       colour    - A colour for the file in hex (FFFFFF) format. Optional.

Most of that should be easy enough to map to something that would make sense from a logline for an ssh attempt. OH! I should mention the source log is RFC3164 formatted. An example of that is:

<86>Aug 22 15:00:54 sooper-awesome-host sshd[18525]: Failed password for root from SOURCE_IP port 42865 ssh2

Lets cover each item in the custom log format one at a time.

  • timestamp
    • Our auth log has a timestamp, but we will need to convert it to a UNIX timestamp.
  • username
    • This one we will map to the IP that made the SSH attempt
  • type
    • We only have 2 types to consider. 'Accepted' and 'Failed'. Lets map 'Failed' to (M)odified and 'Accepted' to (A)dded.
  • file
    • This one will affect how the visualization with look. This one I played around with a lot...still not 100% satisfied with it.

So, from the RFC3164 log example above, once the data has been parsed, we get something like this to feed to Gource:

1500280628|BAD_GUY_IP|M|/M/root/BAD_GUY_IP/1500280628.0.root

Fair warning: I'm just now learning python so this may make a few (all?) of you seasoned Python Veterans throw up a little. That said, here is a quick and dirty python3 script I wrote that will read STDIN, parse, then spit out a formatted line to STDOUT.

import time
import datetime
import datefinder
import re
import sys

for line in sys.stdin:
    if ("Failed" in line) or ("Accepted" in line):
        date_stamp_found = re.findall(r'[A-Za-z]{3}\s\d{1,2}\s(?:\d{1,2}:){2}\d{1,2}', line)
        date_stamp = datefinder.find_dates(str(date_stamp_found))
        if "Failed password for" or "Failed none for" in line:
            if "invalid user" in line:
                line_list = line.split()
                user = line_list[10]
                ip = line_list[12]
            else:
                line_list = line.split()
                user = line_list[8]
                ip = line_list[10]
        elif "Accepted password for" in line:
            line_list = line.split()
            user = line_list[8]
            ip = line_list[10]
        elif "Accepted publickey for" in line:
            line_list = line.split()
            user = line_list[8]
            ip = line_list[10]

        for match in date_stamp:
            unix_stamp = time.mktime(datetime.datetime.strptime(str(match), "%Y-%m-%d %H:%M:%S").timetuple())
            if "Failed" in line:
                event="M"
                event_print="Failed"
            elif "Accepted" in line:
                event="A"
                event_print="Accepted"
            else:
                event="M"
                event_print="Unknown"

            sys.stdout.write('%s|%s|%s|/%s/%s/%s/%s.%s\r\n' % (int(unix_stamp),ip,event,event_print,user,ip,unix_stamp,user))
            sys.stdout.flush()

A simple usage of this would be to cat an RFC3164 ssh log and pipe it into this python script. Then one more pipe into gource.

cat /var/log/secure | python ./secure2gource.py | gource --log-format custom --key --max-files 0 --file-idle-time 0 -

You can even watch a logfile in near realtime!

tail -f /var/log/secure | python ./secure2gource.py | gource --realtime --log-format custom --key --max-files 0 --file-idle-time 0 -

Finally, an example video. Not much different than a normal gource video, except it is visualizing SSH attempts.

Once the dust settles on the video, orbs to the left are all failed attempts and the 15 some-odd orbs down there at the bottom right are actual accepted logins.

Also, since I chose to use the id of the user who is attempting to log in as the file extension, I can use --key in gource to keep a running count of attempts!

Using Gource to Visualize SSH Attempts...Because Why Not?