aboutsummaryrefslogtreecommitdiff
path: root/cowrieder.py
diff options
context:
space:
mode:
authorAda Isopods <me@bathynomus.xyz>2025-05-17 06:18:09 -0600
committerAda Isopods <me@bathynomus.xyz>2026-10-21 23:04:30 -0600
commit0c0c0882c34357c896303a4107691012dc680692 (patch)
tree988cca41fe7e11acbcaafcc69b28d4e74e4dc21f /cowrieder.py
parent8fd7d671c58f7c3b84b0c2ba5fe628742c8c2590 (diff)
fixed ip redaction for verbosity levels above 1
Diffstat (limited to 'cowrieder.py')
-rw-r--r--cowrieder.py27
1 files changed, 21 insertions, 6 deletions
diff --git a/cowrieder.py b/cowrieder.py
index f18d230..36cf1a8 100644
--- a/cowrieder.py
+++ b/cowrieder.py
@@ -23,7 +23,7 @@ parser.add_argument('filepath')
parser.add_argument('-v', '--verbose', action='store_true', help="Make the output more verbose (print abridged logs for all logins where commands are run, not just the interesting ones)")
parser.add_argument('-V', '--verboser', action='store_true', help="Make the output even more verbose (print timestamp, event id, and message (if applicable) for all events)")
-parser.add_argument('-W', '--verbosest', action='store_true', help="Make the output even more verboserer (just group the input log by session id and dump it to pretty-printed JSON)")
+parser.add_argument('-W', '--verbosest', action='store_true', help="Make the output even more verboserer (dump as much information as possible as pretty-printed JSON)")
parser.add_argument('-P', '--pings', action='store_true', help='Include only connections where no authentication attempt was made')
parser.add_argument('-F', '--fails', action='store_true', help='Include only failed logins')
@@ -192,9 +192,6 @@ def load_json_to_array(fp):
):
session_id = entry['session']
- if(args.redact_ip):
- entry['src_ip'] = hashgen(entry['src_ip'])
-
if(session_id not in sessions):
sessions.update({session_id: [entry]})
else:
@@ -221,6 +218,14 @@ newsessions = sessions.copy()
for session_id in sessions:
session = sessions[session_id]
+ if(args.redact_ip):
+ src_ip = session_ip(session)
+ dst_ip = session[0]['dst_ip']
+ for i, event in enumerate(session):
+ for a in event:
+ if(isinstance(event[a], str)):
+ newsessions[session_id][i][a] = event[a].replace('127.0.0.1', 'localhost').replace(src_ip, hashgen(src_ip)).replace(dst_ip, 'Host IP')
+
if(blankmode and (
(not include_empty_pings and not session_attempted_login(session))
or (not include_failed_logins and session_attempted_login(session) and not session_login_succeeded(session))
@@ -234,6 +239,10 @@ sessions = newsessions
# Statistics Aggregation
+login_combos = {}
+
+# Stats pertaining to source IPs
+
attempt_counts_by_ip = {}
ips_by_attempt_count = {}
def top_n_percent_of_ips_session_percent(n): # pretty self explanatory. Pass a float between 0 and 1
@@ -247,7 +256,6 @@ def top_n_percent_of_ips_session_percent(n): # pretty self explanatory. Pass a f
i += 1
return int(c / len(sessions) * 100)
-
for s_id in sessions:
s = sessions[s_id]
ip = session_ip(s)
@@ -255,6 +263,7 @@ for s_id in sessions:
attempt_counts_by_ip.update({ip: 1})
else:
attempt_counts_by_ip[ip] += 1
+
attempt_counts_by_ip = dict(sorted(attempt_counts_by_ip.items(), key=lambda item: item[1], reverse=True))
for ip in attempt_counts_by_ip:
if(attempt_counts_by_ip[ip] not in ips_by_attempt_count):
@@ -284,7 +293,13 @@ def printstats():
# Printing logic coming up
if(verbosity == 3): # Maximum verbosity: literally just dump the now-sorted-by-session logs as pretty-printed JSON
- print(json.dumps(sessions, indent=4))
+ percentiles = {
+ "50%": top_n_percent_of_ips_session_percent(0.5),
+ "10%": top_n_percent_of_ips_session_percent(0.1),
+ "1%": top_n_percent_of_ips_session_percent(0.01),
+ "1": int(attempt_counts_by_ip[next(iter(attempt_counts_by_ip))] / len(sessions) * 100),
+ }
+ print(json.dumps([sessions, ips_by_attempt_count, attempt_counts_by_ip, percentiles], indent=4))
exit()
elif(verbosity == 2): # High verbosity mode: print timestamp, event type and message (if applicable) for every event. I could probably do better but I'm lazy