aboutsummaryrefslogtreecommitdiff
path: root/cowrieder.py
blob: 267d97ebb8f011a7ea7be07c302a7f40558824c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import json
import sys
import random
import os

def ccgen(seed=""): # Color code generator
  if(not os.isatty(1)): # Do not output color code at all if output is not a TTY that can accept them
    return ""
  if(seed and seed != "reset" and seed != "RESET"): # If seed is provided, use it to generate a color. Return color reset code otherwise or if seed is the word "reset"
    random.seed(seed)
    return "\x1b[38;2;{r};{g};{b}m".format(r=random.randrange(50, 256), g=random.randrange(50, 256), b=random.randrange(50, 256))
  return "\x1b[0m"

if not 0 <= 1 < len(sys.argv): # TODO: integrate argparse
  print("Provide a path to a Cowrie JSON log file")
  exit()
filepath = sys.argv[1]

verbosity = 0
entries = []
sessions = {}
session_ips = {}
session_timestamps = {}
session_durations = {}
session_ran_command = {}
session_successful_login = {}

with open(filepath, "r") as logfile:
  for line in logfile:
    entry = json.loads(line)
    entries.append(entry)
    session_id = entry['session']

    if(session_id not in sessions):
      sessions.update({session_id: [entry]})
      session_ips.update({session_id: entry['src_ip']})
    else:
      sessions[session_id].append(entry)

    if(entry["eventid"] == "cowrie.session.connect" and session_id not in session_timestamps): # Save the timestamp of the session's initial connection
      session_timestamps.update({session_id: entry['timestamp']})

    if(entry["eventid"] == "cowrie.session.closed" and session_id not in session_durations): # Save the session's duration
      session_durations.update({session_id: entry['duration']})

    if(entry["eventid"] == "cowrie.command.input" and session_id not in session_ran_command): # Save whether any commands were run during the session
      session_ran_command.update({session_id: True})

    if(entry["eventid"] == "cowrie.login.success" and session_id not in session_successful_login): # Save if login was a success
      session_successful_login.update({session_id: True})

    if(entry["eventid"] == "cowrie.login.failed" and session_id not in session_successful_login): # Save if login failed
      session_successful_login.update({session_id: False})

    if(entry["eventid"] == "cowrie.login.success" and session_id in session_successful_login): # Save if login succeeded after failing
      session_successful_login[session_id] = True

filter_ip = ""
if 0 <= 2 < len(sys.argv):
  filter_ip = sys.argv[2]

if(verbosity == 1): # Verbose mode: print timestamp, event type and message (if applicable) for every event. I could probably do better but I'm lazy
  for session_id in sessions:
    ip = session_ips[session]
    if(ip == filter_ip or not filter_ip):        
      print("\n--- Session " + ccgen(session_id) + session_id + ccgen() + " from " + ccgen(ip) + session_ips[session_id] + ccgen() +" ---")
      for entry in sessions[session_id]:
        if(entry['message']):
          eventid = entry['eventid']
          print(entry["timestamp"] + " > " + eventid + (" " * (29 - len(eventid))) + ": " + entry['message'])
        else:
          print(entry["timestamp"] + " > " + entry['eventid'])

elif(verbosity == 2): # Maximum verbosity: basically just pretty print the now-sorted-by-session logs
  print(json.dumps(sessions, indent=4))

else: # Default verbosity: just the good stuff
  for session_id in sessions:
    ip = session_ips[session_id]
    timestamp = session_timestamps[session_id][:22].replace("T", " ")
    if(session_id not in session_successful_login):
      print(timestamp + " > Ping from " + ccgen(ip) + ip + ccgen() + " lasting " + session_durations[session_id] + "s")
    elif(not session_successful_login[session_id]):
      cred_combos = []
      for entry in sessions[session_id]:
        if(entry["eventid"] == "cowrie.login.failed"):
          cred_combos.append((entry["username"], entry["password"]))
      print(timestamp + " > Failed login attempt from " + ccgen(ip) + ip + ccgen() + " with credentials " + str(cred_combos))
    elif(session_id in session_ran_command):
      print(timestamp + " > Session from " + ccgen(ip) + ip + ccgen() + ":")
      for entry in sessions[session_id]:
        match(entry["eventid"]):
          case "cowrie.login.failed":
            print(" | Failed login attempt: " + entry["username"] + "/" + entry["password"])
          case "cowrie.login.success":
            print(" | Successful login: " + entry["username"] + "/" + entry["password"])
          case "cowrie.command.input":
            print(" | CMD: " + entry["input"])
      print(" \ Disconnected after " + session_durations[session_id] + "s")
    else:
      cred_combos = []
      for entry in sessions[session_id]:
        if(entry["eventid"] == "cowrie.login.failed" or entry["eventid"] == "cowrie.login.success"):
          cred_combos.append((entry["username"], entry["password"]))
      print(timestamp + " > Successful login from " + ccgen(ip) + ip + ccgen() + " with credentials " + str(cred_combos))