-
Notifications
You must be signed in to change notification settings - Fork 9
add support for h0neytr4p v0.4 #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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: | ||
| 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) | ||
|
|
@@ -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: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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']) | ||
|
|
@@ -53,4 +138,4 @@ def h0neytr4p(ECFG): | |
| break | ||
|
|
||
| h0neytr4p.finAlert() | ||
| return() | ||
| return() | ||
There was a problem hiding this comment.
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
ifto prevent possible duplication ofpayloaddir.