fix(profiler): aggregate bash PROMPT_COMMAND lines into attacker profile
SSH/telnet decky containers emit shell commands via `logger -t bash "CMD …"`
which produces RFC 5424 lines with MSGID=NIL. Both parsers were leaving
event_type="-", so the behavioral profiler's `_COMMAND_EVENT_TYPES` filter
silently dropped them — the IP profile existed but no command transcripts
or artifacts. Confirmed in the wild: 44/48 events from one attacker were
event_type="-".
Rewrite event_type to "command" in both parsers when MSGID=NIL and the
msg starts with "CMD ". Correlation parser also extracts the cmd= payload
into fields["command"] so the profiler can build the transcript; collector
parser leaves fields={} to avoid duplicate pills in the dashboard.
This commit is contained in:
@@ -137,6 +137,18 @@ def parse_line(line: str) -> LogEvent | None:
|
||||
msg = tail.group(1).strip() if tail else ""
|
||||
attacker_ip = _extract_attacker_ip(fields, msg)
|
||||
|
||||
# Free-form bash PROMPT_COMMAND lines arrive with MSGID=NIL and a body
|
||||
# like `CMD uid=0 user=root src=… pwd=… cmd=<rest of line>`. Without
|
||||
# this rewrite they're invisible to the behavioral profiler, which
|
||||
# filters on event_type ∈ {command, exec, query, …}.
|
||||
if event_type == "-" and msg.startswith("CMD "):
|
||||
event_type = "command"
|
||||
head, sep, cmd_rest = msg[4:].partition("cmd=")
|
||||
for k, v in re.findall(r'(\w+)=(\S+)', head):
|
||||
fields.setdefault(k, v)
|
||||
if sep:
|
||||
fields.setdefault("command", cmd_rest)
|
||||
|
||||
# Mutator-emitted transitions arrive on the same ingest stream but
|
||||
# belong in the substrate-state index, not the per-IP attacker one.
|
||||
kind: EventKind = (
|
||||
|
||||
Reference in New Issue
Block a user