From 791eab614ded59048e0ffd65660b14e1e6804c27 Mon Sep 17 00:00:00 2001 From: Ada Isopods Date: Sat, 31 May 2025 06:50:54 -0600 Subject: HTML webpage output. I know the code sucks don't @ me --- cowrieder.py | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 498 insertions(+), 2 deletions(-) (limited to 'cowrieder.py') diff --git a/cowrieder.py b/cowrieder.py index 4162a40..85c2485 100644 --- a/cowrieder.py +++ b/cowrieder.py @@ -46,6 +46,7 @@ parser.add_argument('-c', '--no-color', action='store_true', help="Don't color-c parser.add_argument('-s', '--stats', action='store_true', help='Print aggregated statistics') parser.add_argument('-S', '--only-stats', action='store_true', help='Print only aggregated statistics') +parser.add_argument('-m', '--html', action='store_true', help="Output an overview as an HTML webpage, GoAccess-style. Ignores previous two options.") def ccgen(seed=""): # Color code generator if(not os.isatty(1) or args.no_color): # Do not output color code at all if output is not a TTY that can accept them @@ -510,7 +511,7 @@ elif(verbosity == 2): # High verbosity mode: print timestamp, event type and mes -else: # Default (low) verbosity: just the good stuff +elif(not args.html): # Default (low) verbosity: just the good stuff if(not args.only_stats): for session_id in sessions: @@ -586,4 +587,499 @@ else: # Default (low) verbosity: just the good stuff print("\n--- Top IPs with credential combos tried: ---") print_dict_of_lists(login_combos_by_ip, truncate=7, limit = 20, key_is_ip=True) print_percentage_stats() - print("---\nTook {}s to parse {} of logs".format(str(log_parsing_time)[:4], sizeof_fmt(total_filesize))) \ No newline at end of file + print("---\nTook {}s to parse {} of logs".format(str(log_parsing_time)[:4], sizeof_fmt(total_filesize))) + +elif(args.html): + # This is a bad way to do it but it's the way I'm gonna. fuck you + print('') + print('') + print(' ') + print(' ') + print(' Cowrie Stats') + print(' ') + print('') + print('') + print('
') + print(' ') + print('
') + print('

Cowrie Stats

') + print('

' + session_timestamp(sessions[next(iter(sessions))])[:10] + ' – ' + session_timestamp(sessions[next(reversed(sessions))])[:10] + '

') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
Total Sessions
') + print(' '+str(len(sessions))) + print('
') + print('
') + print('
Distinct Visitors
') + print(' '+str(len(attempt_counts_by_ip))) + print('
') + print('
') + print('
Files Saved
') + print(' '+str(cnt_filessaved)) + print('
') + print('
') + print('
Log Parsing Time
') + print(' '+str(log_parsing_time)[:4]+'s') + print('
') + print('
') + print('
Total Log Size
') + print(' '+sizeof_fmt(total_filesize)) + print('
') + print('
') + print('
Updated
') + print(' '+time.strftime("%Y-%m-%d %H:%M:%S%z")) + print('
') + print('
') + + if(args.pings or args.fails or args.logins or args.commands or args.eventful or args.filter_username or args.filter_password or args.filter_sensor or args.filter_ip): + print('

Active Filters

') + print('
') + if(args.filter_ip): + print('
') + print('
By IP
') + print(' '+args.filter_ip) + print('
') + if(args.filter_username): + print('
') + print('
By Username Used
') + print(' '+args.filter_username) + print('
') + if(args.filter_password): + print('
') + print('
By Password Used
') + print(' '+args.filter_password) + print('
') + if(args.filter_sensor): + print('
') + print('
By Sensor
') + print(' '+args.filter_sensor) + print('
') + if(args.pings or args.fails or args.logins or args.commands or args.eventful): + print('
') + print('
By Session Type
') + h_typefilters = ' ' + h_typefiltercnt = 0 + if(args.pings): + h_typefilters += 'NoLogin' + h_typefiltercnt += 1 + if(args.fails): + if(h_typefiltercnt > 0): + h_typefilters += ', ' + h_typefilters += 'Failed' + h_typefiltercnt += 1 + if(args.logins): + if(h_typefiltercnt > 0): + h_typefilters += ', ' + h_typefilters += 'NoCommands' + h_typefiltercnt += 1 + if(args.commands): + if(h_typefiltercnt > 0): + h_typefilters += ', ' + h_typefilters += 'Commands' + h_typefiltercnt += 1 + if(args.eventful): + if(h_typefiltercnt > 0): + h_typefilters += ', ' + h_typefilters += 'Eventful' + print(h_typefilters) + print('
') + print('
') + print('
') + print('
') + print('

Sessions by Source IP

') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
') + print('') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
    ') + print('
  • '+str(100 - top_n_percent_of_ips_session_percent(0.5))+'% – Bottom 50%
  • ') + print('
  • '+str(top_n_percent_of_ips_session_percent(0.5))+'% – Top 50%
  • ') + print('
  • '+str(top_n_percent_of_ips_session_percent(0.1))+'% – Top 10%
  • ') + print('
  • '+str(top_n_percent_of_ips_session_percent(0.01))+'% – Top 1%
  • ') + print('
  • '+str(percent_of_all_sessions(attempt_counts_by_ip[next(iter(attempt_counts_by_ip))]))+'% – Top 1 ('+next(iter(attempt_counts_by_ip))+')
  • ') + print('
') + print('
') + print('
') + print('
') + print('
') + print('

Sessions by Type

') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
') + print('') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
    ') + print('
  • '+str(percent_of_all_sessions(cnt_pings))+'% – No attempt to log in
  • ') + print('
  • '+str(percent_of_all_sessions(cnt_fails))+'% – Failed logins
  • ') + print('
  • '+str(percent_of_all_sessions(cnt_lping + cnt_cmdping + cnt_eventful))+'% – Successful logins
  • ') + print('
  • '+str(percent_of_all_sessions(cnt_cmdping + cnt_eventful))+'% – Logins that ran commands
  • ') + print('
  • '+str(percent_of_all_sessions(cnt_eventful))+'% – Logins that ran unusual* commands
  • ') + print('
') + print('

*Not a subset of '+str(cmdping_commands)+'

') + print('
') + print('
') + print('
') + print('
') + print('
') + print('
') + print('

Attempts by username

') + print('

Expand to show corresponding passwords

') + print('
    ') + for uname in passwords_by_username: + print('
  • ') + print('
    ') + print(' '+uname+' – '+str(attempt_counts_by_username[uname])+' Attempts') + print('
      ') + for pw in passwords_by_username[uname]: + print('
    • '+pw+'
    • ') + print('
    ') + print('
    ') + print('
  • ') + print('
') + print('
') + print('
') + print('

Attempts by IP

') + print('

Expand to show corresponding credential combos

') + print('
    ') + for ip in login_combos_by_ip: + print('
  • ') + print('
    ') + print(' '+ip+' – '+str(attempt_counts_by_ip[ip])+' Attempts') + print('
      ') + for combo in login_combos_by_ip[ip]: + print('
    • '+combo[0]+' : '+combo[1]+'
    • ') + print('
    ') + print('
    ') + print('
  • ') + print('
') + print('
') + print('
') + print('

Total Attempts Per Password

') + print('
    ') + for pw in attempt_counts_by_password: + if(pw =='[SSH_PUBKEY_ATTEMPT]'): + print('
  • (SSH Public Key) × '+str(attempt_counts_by_password[pw])+'
  • ') + else: + print('
  • '+pw+' × '+str(attempt_counts_by_password[pw])+'
  • ') + print('
') + print('
') + if(cnt_eventful > 0): + print('
') + print('

') + print(' ') + print(' ') + print(' ') + print(' ') + print(' Sessions of Particular Note') + print('

') + print('
    ') + for s_id in sessions: + session = sessions[s_id] + if(session_ran_command(session) and not session_is_cmdping(session)): + print('
  • ') + print(' '+session_ip(session)+' @ '+session_timestamp(session)[:19].replace('T', ' ')+':') + print('
      ') + for entry in session: + match(entry["eventid"]): + case "cowrie.login.failed": + print('
    • ') + print(' ') + pw = entry['password'] + if(pw =='[SSH_PUBKEY_ATTEMPT]'): + pw = ' (SSH Public Key)' + print(' ' + entry["username"] + ' : ' + pw) + print('
    • ') + case "cowrie.login.success": + print('
    • ') + print(' ') + pw = entry['password'] + if(pw =='[SSH_PUBKEY_ATTEMPT]'): + pw = ' (SSH Public Key)' + print(' ' + entry["username"] + ' : ' + pw) + print('
    • ') + case "cowrie.command.input": + print('
    • ') + print(' ') + print(' '+entry['input']+'') + print('
    • ') + case "cowrie.session.file_download": + df = "file" + if("url" in entry): + df = entry["url"] + elif("destfile" in entry): + df = entry["destfile"] + print('
    • ') + print(' ') + print(' Saved '+df+' to '+entry["outfile"][:50]+'...') + print('
    • ') + print('
    • ') + print(' ') + print(' Closed after '+str(session_duration(session))+'s') + print('
    • ') + print('
    ') + print('
  • ') + print('
') + print('
') + print('
') + print('
') + print(' ') + print('') \ No newline at end of file -- cgit v1.2.3