From b1a834137148f46828bbb087fdfacb3b7003d280 Mon Sep 17 00:00:00 2001 From: Ruben Groenewoud <78494512+Aegrah@users.noreply.github.com> Date: Fri, 31 Jan 2025 15:44:38 +0100 Subject: [PATCH] [Hunt Tuning] Logon Activity by Source IP (#4428) --- hunting/index.md | 2 +- hunting/linux/docs/login_activity_by_source_address.md | 8 +++++--- hunting/linux/docs/persistence_via_package_manager.md | 2 +- .../linux/queries/login_activity_by_source_address.toml | 9 +++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/hunting/index.md b/hunting/index.md index 2d988789a..edd8d5d6f 100644 --- a/hunting/index.md +++ b/hunting/index.md @@ -44,8 +44,8 @@ Here are the queries currently available: - [Persistence via DPKG/RPM Package](./linux/docs/persistence_via_rpm_dpkg_installer_packages.md) (ES|QL) - [Persistence via Docker Container](./linux/docs/persistence_via_malicious_docker_container.md) (ES|QL) - [Persistence via Dynamic Linker Hijacking](./linux/docs/persistence_via_dynamic_linker_hijacking.md) (ES|QL) -- [Persistence via Initramfs](./linux/docs/persistence_via_initramfs.md) (ES|QL) - [Persistence via GRUB Bootloader](./linux/docs/persistence_via_grub_bootloader.md) (ES|QL) +- [Persistence via Initramfs](./linux/docs/persistence_via_initramfs.md) (ES|QL) - [Persistence via Loadable Kernel Modules](./linux/docs/persistence_via_loadable_kernel_modules.md) (ES|QL) - [Persistence via Message-of-the-Day](./linux/docs/persistence_via_message_of_the_day.md) (ES|QL) - [Persistence via Package Manager](./linux/docs/persistence_via_package_manager.md) (ES|QL) diff --git a/hunting/linux/docs/login_activity_by_source_address.md b/hunting/linux/docs/login_activity_by_source_address.md index a02ec09bf..e2bc438d4 100644 --- a/hunting/linux/docs/login_activity_by_source_address.md +++ b/hunting/linux/docs/login_activity_by_source_address.md @@ -16,13 +16,15 @@ ```sql from logs-system.auth-* +| mv_expand event.category | where @timestamp > now() - 7 day | where host.os.type == "linux" and event.category == "authentication" and event.action in ("ssh_login", "user_login") and - event.outcome == "failure" and source.ip IS NOT null and not CIDR_MATCH(source.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1") + event.outcome in ("failure", "success") and source.ip is not null and + not CIDR_MATCH(source.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1") | eval failed = case(event.outcome == "failure", source.ip, null), success = case(event.outcome == "success", source.ip, null) | stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(user.name) by source.ip - /* below threshold should be adjusted to your env logon patterns */ -| where count_failed >= 100 and count_success <= 10 and count_user >= 20 +/* below threshold should be adjusted to your env logon patterns */ +| where count_failed >= 100 and count_user >= 20 ``` ## Notes diff --git a/hunting/linux/docs/persistence_via_package_manager.md b/hunting/linux/docs/persistence_via_package_manager.md index 5a0b20a32..44e7a44ed 100644 --- a/hunting/linux/docs/persistence_via_package_manager.md +++ b/hunting/linux/docs/persistence_via_package_manager.md @@ -59,7 +59,7 @@ SELECT g.groupname AS group owner, datetime(f.atime, 'unixepoch') AS file_last_access time, datetime(f.mtime, 'unixepoch') AS file last_modified time, - datetime(f.ctime, 'unixepoch') AS file last_status change time, + datetime(f.ctime, 'unixepoch') AS file last_status_change time, datetime(f.btime, 'unixepoch') AS file created time, f.size AS size bytes FROM diff --git a/hunting/linux/queries/login_activity_by_source_address.toml b/hunting/linux/queries/login_activity_by_source_address.toml index 5000dd307..03582f007 100644 --- a/hunting/linux/queries/login_activity_by_source_address.toml +++ b/hunting/linux/queries/login_activity_by_source_address.toml @@ -14,16 +14,17 @@ notes = [ "The thresholds for failed attempts, successful logons, and distinct usernames should be adjusted based on the environment's normal logon patterns." ] mitre = ["T1110", "T1078"] - query = [ ''' from logs-system.auth-* +| mv_expand event.category | where @timestamp > now() - 7 day | where host.os.type == "linux" and event.category == "authentication" and event.action in ("ssh_login", "user_login") and - event.outcome == "failure" and source.ip IS NOT null and not CIDR_MATCH(source.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1") + event.outcome in ("failure", "success") and source.ip is not null and + not CIDR_MATCH(source.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1") | eval failed = case(event.outcome == "failure", source.ip, null), success = case(event.outcome == "success", source.ip, null) | stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(user.name) by source.ip - /* below threshold should be adjusted to your env logon patterns */ -| where count_failed >= 100 and count_success <= 10 and count_user >= 20 +/* below threshold should be adjusted to your env logon patterns */ +| where count_failed >= 100 and count_user >= 20 ''' ]