Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 102 additions & 17 deletions honeypots/h0neytr4p.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,65 @@
# honeypots/h0neytr4p.py

from datetime import datetime
from urllib import parse
import os
import time
from modules.ealert import EAlert
from datetime import datetime


def _format_timezone(offset):
seconds = int(offset.total_seconds())
sign = '+' if seconds >= 0 else '-'
seconds = abs(seconds)
hours, seconds = divmod(seconds, 3600)
minutes = seconds // 60
return f"{sign}{hours:02d}{minutes:02d}"


def _parse_timestamp(timestamp):
dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))

if dt.tzinfo is not None and dt.utcoffset() is not None:
timezone = _format_timezone(dt.utcoffset())
else:
timezone = time.strftime('%z')

return dt.strftime('%Y-%m-%d %H:%M:%S'), timezone


def _payload_path(line, payloaddir):
payload_filename = line.get('payload_filename')
payload_hash = line.get('payload_hash_md5')
candidates = []

if payload_filename:
if os.path.isabs(payload_filename):
candidates.append(payload_filename)
elif payloaddir:
candidates.append(os.path.join(payloaddir, payload_filename))

if payloaddir and payload_filename:
candidates.append(os.path.join(payloaddir, os.path.basename(payload_filename)))

if payloaddir and payload_hash:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would elif that with the preceding if to prevent possible duplication of payloaddir.

candidates.append(os.path.join(payloaddir, payload_hash))

for candidate in candidates:
if os.path.isfile(candidate):
return candidate

return candidates[0] if candidates else None


def _add_metadata(alert, line, keys):
for key in keys:
if key in line:
alert.adata(key, line[key])


def _add_prefixed_metadata(alert, line, prefixes):
for key, value in line.items():
if key.startswith(prefixes):
alert.adata(key, value)


def h0neytr4p(ECFG):
h0neytr4p = EAlert('h0neytr4p', ECFG)
Expand All @@ -21,30 +78,58 @@ def h0neytr4p(ECFG):
break
if line == 'jsonfail':
continue

h0neytr4p.data('analyzer_id', HONEYPOT['nodeid']) if 'nodeid' in HONEYPOT else None

h0neytr4p.data('timestamp', datetime.fromisoformat(line['timestamp']).strftime('%Y-%m-%d %H:%M:%S'))
h0neytr4p.data("timezone", time.strftime('%z'))
if 'timestamp' in line:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change the timestamp parsing here? The logs for testing do not need that change because they already are in isoformat. I would remove the helper methods, because they are redundant and python datetime is able to do the same.

We drop all alerts that don't contain the timestamp so I would remove the condition.

Let's implement it like that if we don't need the actual timezone of the honeypot. If we need that, we should refactor all honeypots at the same time so all use the exact same logic.

h0neytr4p.data('timestamp', datetime.fromisoformat(line['timestamp'].replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S'))
h0neytr4p.data('timezone', time.strftime('%z'))

timestamp, timezone = _parse_timestamp(line['timestamp'])
h0neytr4p.data('timestamp', timestamp)
h0neytr4p.data("timezone", timezone)

h0neytr4p.data('source_address', line['src_ip'] ) if 'src_ip' in line else None
h0neytr4p.data('target_address', ECFG['ip_ext'])
h0neytr4p.data('source_port', '0') # No source_port in logs :-(
h0neytr4p.data('source_port', '0') # No source_port in logs :-(
h0neytr4p.data('target_port', line['dest_port'] ) if 'dest_port' in line else None
h0neytr4p.data('source_protocol', "tcp")
h0neytr4p.data('target_protocol', "tcp")

h0neytr4p.request("description", "H0neytr4p Honeypot")
h0neytr4p.request("url", parse.quote(str(line['request_uri']).encode('ascii', 'ignore'))) if 'request_uri' in line else None

if 'request_method' in line:
h0neytr4p.adata('httpmethod', line['request_method'])

_add_metadata(h0neytr4p, line, [
'protocol',
'hostname',
'request_proto',
'request_uri',
'user-agent',
'user-agent_browser',
'user-agent_browser_version',
'user-agent_os',
'trapped',
'trapped_for',
'trapped_references',
'trapped_risk_rating',
])
_add_prefixed_metadata(h0neytr4p, line, ('header_', 'cookie_', 'payload_'))

if ECFG['send_malware'] is True and ('payload_filename' in line or 'payload_hash_md5' in line):
payload_path = _payload_path(line, HONEYPOT.get('payloaddir'))
if payload_path:
payload_md5 = line.get('payload_hash_md5') or os.path.basename(payload_path)
error, payload = h0neytr4p.malwarecheck(
os.path.dirname(payload_path),
os.path.basename(payload_path),
ECFG['del_malware_after_send'],
payload_md5
)
if (error is True) and (len(payload) <= 5 * 1024) and (len(payload) > 0):
h0neytr4p.request('binary', payload.decode('utf-8'))
elif (error is True) and (len(payload) > 0):
h0neytr4p.request('largepayload', payload.decode('utf-8'))

h0neytr4p.adata('user-agent', line['user-agent']) if 'user-agent' in line else None
h0neytr4p.adata('user-agent_browser', line['user-agent_browser']) if 'user-agent_browser' in line else None
h0neytr4p.adata('user-agent_browser_version', line['user-agent_browser_version']) if 'user-agent_browser_version' in line else None
h0neytr4p.adata('user-agent_os', line['user-agent_os']) if 'user-agent_os' in line else None

h0neytr4p.adata('trapped', line['trapped']) if 'trapped' in line else None
h0neytr4p.adata('trapped_for', line['trapped_for']) if 'trapped_for' in line else None
h0neytr4p.adata('request_uri', line['request_uri']) if 'request_uri' in line else None

h0neytr4p.adata('externalIP', ECFG['ip_ext'])
h0neytr4p.adata('internalIP', ECFG['ip_int'])
h0neytr4p.adata('uuid', ECFG['uuid'])
Expand All @@ -53,4 +138,4 @@ def h0neytr4p(ECFG):
break

h0neytr4p.finAlert()
return()
return()
Loading