diff options
| author | Ada Isopods <me@bathynomus.xyz> | 2025-05-16 03:24:45 -0600 |
|---|---|---|
| committer | Ada Isopods <me@bathynomus.xyz> | 2026-10-21 23:04:27 -0600 |
| commit | f9b2e6c3a550256b62c156d948f2bfdd288e482f (patch) | |
| tree | ea13b4b7d98f6c8ac0ce8947f18a23be20f2914e | |
| parent | c21ad820902c69b1bffa4c6453c0e1a15f07fe8c (diff) | |
readme update + make that filter by hash thing real
| -rw-r--r-- | README.md | 14 | ||||
| -rw-r--r-- | cowrieder.py | 26 |
2 files changed, 26 insertions, 14 deletions
@@ -13,14 +13,14 @@ Options: -v, --verbose Make the output more verbose (print abridged logs for all logins where commands are run, not just the interesting ones) -vv, --verboser Make the output even more verbose (print timestamp, event id, and message (if applicable) for all events) -vvv, --verbosest Make the output even more verboserer (just group the input log by session id and dump it to pretty-printed JSON) --B, --blank Print nothing whatsoever. Override this with other arguments to filter for only the stuff you care about --P, --pings | With blank mode active, print "empty pings" --F, --fails | With blank mode active, print failed logins --L, --logins | With blank mode active, print "login pings" --C, --commands | With blank mode active, print "command pings" --S, --sessions * With blank mode active, print the cool interesting sessions that aren't any of that other stuff. +-P, --pings Print only "empty pings" +-F, --fails Print only failed logins +-L, --logins Print only "login pings" +-C, --commands Print only "command pings" +-S, --sessions Print only the cool interesting sessions that aren't any of that other stuff. +-r, --redact-ip Redact IP addresses by converting them to 16-character hashes -i, --filter-ip FILTER_IP - Filter data to a specific IP + Filter data to a specific IP or censored hash thereof ``` # Terminology diff --git a/cowrieder.py b/cowrieder.py index f022d4c..44051af 100644 --- a/cowrieder.py +++ b/cowrieder.py @@ -44,6 +44,11 @@ def ppip(addr, spacing = False, ttycolor = False): # Pretty-print an address wit rs = rs + (" " * (15 - len(addr))) return rs +def hashgen(seed, length=16): + if(length % 2): + raise Warning("Due to strange behaviour on the part of the hexdigest() function, length should be a multiple of 2") + return hashlib.shake_256(str(seed).encode("utf-8")).hexdigest(int(length / 2)) + parser = argparse.ArgumentParser( description="Script to parse JSON logs from popular SSH honeypot Cowrie and print them in a more readable format" ) @@ -63,11 +68,12 @@ parser.add_argument('-S', '--sessions', action='store_true', help='Print only th parser.add_argument('-r', '--redact-ip', action='store_true', help='Redact IP addresses by converting them to 16-character hashes') parser.add_argument('-i', '--filter-ip', help='Filter data to a specific IP or censored hash thereof') -#parser.add_argument('-a', '--stats', action='store_true', help='Print aggregated statistics') -#parser.add_argument('-j', '--json-stats', action='store_true', help='Dump aggregated statistics as JSON') -#print_stats = args.stats or args.json_stats +parser.add_argument('-a', '--stats', action='store_true', help='Print aggregated statistics') +parser.add_argument('-j', '--json-stats', action='store_true', help='Dump aggregated statistics as JSON') + args = parser.parse_args() +print_stats = args.stats or args.json_stats filepath = args.filepath @@ -98,7 +104,7 @@ with open(filepath, "r") as logfile: entry = json.loads(line) if( - (not args.filter_ip or entry["src_ip"] == args.filter_ip) # If it's not the IP we're filtering for don't even bother man + (not args.filter_ip or entry["src_ip"] == args.filter_ip or hashgen(entry["src_ip"]) == args.filter_ip) # If it's not the IP we're filtering for don't even bother man ): entries.append(entry) session_id = entry['session'] @@ -106,7 +112,7 @@ with open(filepath, "r") as logfile: if(session_id not in sessions): sessions.update({session_id: [entry]}) if(args.redact_ip): - session_ips.update({session_id: hashlib.shake_256(entry['src_ip'].encode("utf-8")).hexdigest(8)}) + session_ips.update({session_id: hashgen(entry['src_ip'])}) else: session_ips.update({session_id: entry['src_ip']}) else: @@ -146,7 +152,7 @@ with open(filepath, "r") as logfile: # Blank Mode logic -if(args.blank): +if(blankmode): newsessions = sessions.copy() for session_id in sessions: @@ -228,7 +234,10 @@ else: # Default (low) verbosity: just the good stuff df = entry["url"] elif("destfile" in entry): df = entry["destfile"] - print(" | Saved file " + df + " to " + entry["outfile"][:40]) + if(args.verbose): + print(" | Saved file " + df + " to " + entry["outfile"]) + else: + print(" | Saved file " + df + " to " + entry["outfile"][:40] + "...") print(" X Disconnected after " + session_durations[session_id] + "s") else: # Printing logic for successful logins in which no commands were run @@ -237,3 +246,6 @@ else: # Default (low) verbosity: just the good stuff if(entry["eventid"] == "cowrie.login.failed" or entry["eventid"] == "cowrie.login.success"): cred_combos.append((entry["username"], entry["password"])) print(timestamp + " > " + ppip(ip, True, True) + " > " + ccgen("GREEN") + "Login ping" + ccgen() + ": " + str(cred_combos)) + +if(args.stats): + print("Aggregate statistics")
\ No newline at end of file |
