Skip to content

[Rule Tuning] login_activity_by_source_address.toml #4287

@farbod-sec

Description

@farbod-sec

Link to Rule

https://github.com/elastic/detection-rules/blob/main/hunting/linux/queries/login_activity_by_source_address.toml

Rule Tuning Type

False Negatives - Enhancing detection of true threats that were previously missed.

Description

The detection logic will not work for the authentication success count (count_success)

from logs-system.auth-* | 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") | 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

If you look at these two lines:

| 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") | eval failed = case(event.outcome == "failure", source.ip, null), success = case(event.outcome == "success", source.ip, null)

The first WHERE clause specifically says: and event.outcome == "failure"

but the second EVAL is doing a case condition to count how many event.outcome == successes there would be when they would never exist with the filter looking only for failure logs.

The other possible issue is that event.category can be an ARRAY and doing a MV string match against an array is not currently supported in ES|QL. At least in my labs, I'm seeing the event.category == authentication also coupled with a session log, so "event.category: [authentication, success]" then the subsequent NIX logs are session only event category. I'm not sure if its just me on Debian 11 and 12 that experiences this or others. My fix is the following by starting with MV_EXPAND:

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 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

Hope that makes sense! Also let me know if you're seeing the same behavior with the array for event.category always having 2 entries for the authentication log or if its just me.

Example Data

Image

Image

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 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

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions