Query Details

Syslog Failed Logon Attempts Unknown User

Query

let query_frequency = 1h;
let query_period = 2h;
let failures_threshold = 5;
let _InfoInvalidUser =
    Syslog
    | where TimeGenerated > ago(query_period)
    | where SyslogMessage has_any ("invalid user") and not(SyslogMessage has "[preauth]") and Facility in ("auth", "authpriv")
    | parse SyslogMessage with * "user " User:string " from " RemoteIPAddress:string " port " RemotePort:int *
    | summarize hint.strategy=shuffle arg_min(TimeGenerated, *) by HostName, HostIP, ProcessID, RemoteIPAddress, RemotePort
;
let _UserUnknown =
    Syslog
    | where TimeGenerated > ago(query_period)
    | where SyslogMessage has_any ("user unknown") and Facility in ("auth", "authpriv")
    | join kind=leftanti _InfoInvalidUser on HostName, ProcessID
;
union _InfoInvalidUser, _UserUnknown
| as _Events
| join kind=leftsemi (
    _Events
    | evaluate activity_counts_metrics(Type, TimeGenerated, ago(query_period), now(), query_frequency, HostName, HostIP, ProcessName)
    | summarize
        arg_min(PreviousTimeGenerated = TimeGenerated, PreviousCount = ["count"]),
        arg_max(CurrentTimeGenerated = TimeGenerated, CurrentCount = ["count"])
        by HostName, HostIP, ProcessName
    | where CurrentTimeGenerated > ago(query_period)
    | extend PreviousCount = iff(PreviousTimeGenerated == CurrentTimeGenerated, 0, PreviousCount)
    | where (not(PreviousCount > failures_threshold) and CurrentCount > failures_threshold)
        or ((CurrentCount - PreviousCount) > failures_threshold)
    ) on HostName, HostIP, ProcessName
| summarize
    StartTime = min(TimeGenerated),
    EndTime = max(TimeGenerated),
    Count = count(),
    Facilities = array_sort_asc(make_set(Facility)),
    SeverityLevels = array_sort_asc(make_set(SeverityLevel)),
    SyslogMessages = make_list(SyslogMessage, 100),
    take_any(_ResourceId)
    by HostName, HostIP, ProcessName
| project
    StartTime,
    EndTime,
    HostName,
    HostIP,
    Facilities,
    SeverityLevels,
    ProcessName,
    Count,
    SyslogMessages,
    _ResourceId

Explanation

This query is designed to monitor system logs (Syslog) for authentication failures over a period of two hours. It specifically looks for messages indicating an "invalid user" or "user unknown" from the "auth" or "authpriv" facilities.

The query first identifies all instances of these failures, parsing out additional information such as the user, remote IP address, and port from the log message. It then checks for any "user unknown" messages that do not match the "invalid user" messages.

The query then compares the current count of these failures to the previous count, looking for any significant increases (greater than a defined threshold of 5).

Finally, the query summarizes this information, providing the start and end time of the period, the host name and IP, the facilities involved, severity levels, the process name, the total count of failures, and a list of up to 100 of the Syslog messages. It also includes the resource ID.

In simple terms, this query helps to identify and analyze any significant increases in authentication failures in a system over a two-hour period.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: March 21, 2023

Tables

Syslog

Keywords

Syslog,TimeGenerated,SyslogMessage,Facility,User,RemoteIPAddress,RemotePort,HostName,HostIP,ProcessID,Type,PreviousTimeGenerated,CurrentTimeGenerated,PreviousCount,CurrentCount,StartTime,EndTime,Count,Facilities,SeverityLevels,ProcessName,SyslogMessages,ResourceId

Operators

letSyslogwhereTimeGeneratedagohas_anynotinparsesummarizehint.strategy=shufflearg_minbyjoinkind=leftantiunionasevaluateactivity_counts_metricsarg_maxextendiffminmaxcountarray_sort_ascmake_setmake_listtake_anyproject.

Actions