Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
* text=auto
.gitattributes text eol=lf
*.cpp text eol=lf
*.hpp text eol=lf
*.h text eol=lf
Expand All @@ -8,5 +9,6 @@
*.yaml text eol=lf
*.txt text eol=lf
*.csv text eol=lf
*.log text eol=lf
CMakeLists.txt text eol=lf
CMakePresets.json text eol=lf
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ LogLens currently parses and reports these additional auth patterns beyond the c
- `Accepted keyboard-interactive/pam` SSH successes
- `Failed publickey` SSH failures, which count toward SSH brute-force detection by default
- `Failed keyboard-interactive/pam` and `maximum authentication attempts exceeded` SSH failures, which count toward SSH brute-force detection by default
- `sshd`-owned `PAM: Authentication failure ...` lines, with invalid/illegal-user variants normalized to `ssh_invalid_user`
- `input_userauth_request: invalid/illegal user ...` preauth SSH traces normalized to `ssh_invalid_user`
- `sshd`-owned `PAM: Authentication failure ...` lines, including OpenSSH's optional leading `error:` marker, with invalid/illegal-user variants normalized to `ssh_invalid_user`
- `sudo` command, password-failure, and sudoers policy-denial audit lines
- `su` success and failure audit lines
- `pam_unix(...:auth): authentication failure`
Expand Down
1 change: 1 addition & 0 deletions assets/parser_auth_families_journalctl_short_full.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Wed 2026-03-11 10:00:36 UTC example-host sshd[3102]: Failed publickey for invali
Wed 2026-03-11 10:00:38 UTC example-host sshd[3103]: PAM: Authentication failure for alice from 203.0.113.76
Wed 2026-03-11 10:00:39 UTC example-host sshd[3104]: PAM: Authentication failure for invalid user svc-pam from 203.0.113.77
Wed 2026-03-11 10:00:40 UTC example-host sshd[3105]: PAM: Authentication failure for illegal user svc-pam-legacy from 203.0.113.78
Wed 2026-03-11 10:00:41 UTC example-host sshd[3106]: error: PAM: Authentication failure for invalid user svc-pam-error from 203.0.113.79
Wed 2026-03-11 10:00:42 UTC example-host pam_faillock(sshd:auth): Consecutive login failures for user alice account temporarily locked from 203.0.113.71
Wed 2026-03-11 10:01:13 UTC example-host pam_faillock(sshd:auth): Authentication failure for user bob from 203.0.113.72
Wed 2026-03-11 10:01:40 UTC example-host pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=203.0.113.75 user=carol
Expand Down
1 change: 1 addition & 0 deletions assets/parser_auth_families_syslog.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Mar 11 10:00:36 example-host sshd[2102]: Failed publickey for invalid user svc-d
Mar 11 10:00:38 example-host sshd[2103]: PAM: Authentication failure for alice from 203.0.113.76
Mar 11 10:00:39 example-host sshd[2104]: PAM: Authentication failure for invalid user svc-pam from 203.0.113.77
Mar 11 10:00:40 example-host sshd[2105]: PAM: Authentication failure for illegal user svc-pam-legacy from 203.0.113.78
Mar 11 10:00:41 example-host sshd[2106]: error: PAM: Authentication failure for invalid user svc-pam-error from 203.0.113.79
Mar 11 10:00:42 example-host pam_faillock(sshd:auth): Consecutive login failures for user alice account temporarily locked from 203.0.113.71
Mar 11 10:01:13 example-host pam_faillock(sshd:auth): Authentication failure for user bob from 203.0.113.72
Mar 11 10:01:40 example-host pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=203.0.113.75 user=carol
Expand Down
1 change: 1 addition & 0 deletions assets/parser_fixture_matrix_journalctl_short_full.log
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Tue 2026-03-10 09:00:01 UTC example-host sshd[3000]: Failed password for invalid user admin from 203.0.113.10 port 52000 ssh2
Tue 2026-03-10 09:00:40 UTC example-host sshd[3001]: Failed publickey for alice from 203.0.113.11 port 52001 ssh2
Tue 2026-03-10 09:01:15 UTC example-host sshd[3002]: Invalid user backup from 203.0.113.12 port 52002
Tue 2026-03-10 09:01:24 UTC example-host sshd[3027]: input_userauth_request: invalid user svc-verbose [preauth]
Tue 2026-03-10 09:01:52 UTC example-host pam_unix(sshd:auth): authentication failure; user=alice euid=0 tty=ssh rhost=203.0.113.40
Tue 2026-03-10 09:02:30 UTC example-host pam_unix(sudo:session): session opened for user root(uid=0) by alice(uid=1000)
Tue 2026-03-10 09:03:05 UTC example-host pam_unix(su-l:session): session opened for user root by bob(uid=1001)
Expand Down
1 change: 1 addition & 0 deletions assets/parser_fixture_matrix_syslog.log
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Mar 10 09:00:01 example-host sshd[2000]: Failed password for invalid user admin from 203.0.113.10 port 52000 ssh2
Mar 10 09:00:40 example-host sshd[2001]: Failed publickey for alice from 203.0.113.11 port 52001 ssh2
Mar 10 09:01:15 example-host sshd[2002]: Invalid user backup from 203.0.113.12 port 52002
Mar 10 09:01:24 example-host sshd[2027]: input_userauth_request: invalid user svc-verbose [preauth]
Mar 10 09:01:52 example-host pam_unix(sshd:auth): authentication failure; user=alice euid=0 tty=ssh rhost=203.0.113.40
Mar 10 09:02:30 example-host pam_unix(sudo:session): session opened for user root(uid=0) by alice(uid=1000)
Mar 10 09:03:05 example-host pam_unix(su-l:session): session opened for user root by bob(uid=1001)
Expand Down
2 changes: 1 addition & 1 deletion docs/parser-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The parser currently recognizes common authentication evidence from:
- selected `pam_faillock(...)` variants
- selected `pam_sss(...)` variants

Recognized SSH failure families include failed password, invalid user, illegal user, failed publickey, failed keyboard-interactive/pam, failed-none invalid-user probing, `sshd`-owned PAM authentication-failure lines, and maximum-authentication-attempts-exceeded lines. `illegal user` is treated as an OpenSSH wording variant of `invalid user`. Maximum-authentication-attempts lines may include OpenSSH's leading `error:` marker and still normalize into the same event family. Invalid or illegal-user variants of failed-none probing, keyboard-interactive, `sshd`-owned PAM authentication failures, and maximum-authentication-attempts-exceeded lines are normalized into `ssh_invalid_user` events. Recognized SSH failures can become detection signals through the configured signal mapping.
Recognized SSH failure families include failed password, invalid user, illegal user, failed publickey, failed keyboard-interactive/pam, failed-none invalid-user probing, `input_userauth_request` invalid/illegal-user preauth traces, `sshd`-owned PAM authentication-failure lines, and maximum-authentication-attempts-exceeded lines. `illegal user` is treated as an OpenSSH wording variant of `invalid user`. Maximum-authentication-attempts and `sshd`-owned PAM authentication-failure lines may include OpenSSH's leading `error:` marker and still normalize into the same event family. Invalid or illegal-user variants of failed-none probing, `input_userauth_request` preauth traces, keyboard-interactive, `sshd`-owned PAM authentication failures, and maximum-authentication-attempts-exceeded lines are normalized into `ssh_invalid_user` events. Recognized SSH failures can become detection signals through the configured signal mapping.

Recognized success or audit families include accepted password, accepted publickey, accepted keyboard-interactive/pam, sudo command audit lines, sudo password failures, sudoers policy denials, su success/failure audit lines, and selected PAM session/auth lines.

Expand Down
30 changes: 30 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,13 @@ bool parse_ssh_max_auth_tries_message(std::string_view message, Event& event) {
}

bool parse_ssh_pam_auth_failure_message(std::string_view message, Event& event) {
static constexpr std::string_view error_prefix = "error: ";
static constexpr std::string_view pam_auth_prefix = "PAM: Authentication failure for ";

if (message.starts_with(error_prefix)) {
message.remove_prefix(error_prefix.size());
}

if (!message.starts_with(pam_auth_prefix)) {
return false;
}
Expand All @@ -473,6 +479,27 @@ bool parse_ssh_pam_auth_failure_message(std::string_view message, Event& event)
return true;
}

bool parse_ssh_input_userauth_request_message(std::string_view message, Event& event) {
static constexpr std::string_view input_userauth_prefix = "input_userauth_request: ";
if (!message.starts_with(input_userauth_prefix)) {
return false;
}

auto remaining = message.substr(input_userauth_prefix.size());
if (!consume_invalid_or_illegal_user_prefix(remaining)) {
return false;
}

const auto username = consume_token(remaining);
if (username.empty()) {
return false;
}

event.username.assign(username);
event.event_type = EventType::SshInvalidUser;
return true;
}

bool parse_ssh_invalid_user_message(std::string_view message, Event& event) {
static constexpr std::string_view invalid_user_prefix = "Invalid user ";
static constexpr std::string_view illegal_user_prefix = "Illegal user ";
Expand Down Expand Up @@ -768,6 +795,9 @@ bool classify_event(Event& event) {
if (parse_ssh_pam_auth_failure_message(message, event)) {
return true;
}
if (parse_ssh_input_userauth_request_message(message, event)) {
return true;
}
if (parse_ssh_invalid_user_message(message, event)) {
return true;
}
Expand Down
Loading
Loading