Detection rules › Kusto
GitLab - Brute-force Attempts
'This query relies on GitLab Application Logs to get failed logins to highlight brute-force attempts from different IP addresses in a short space of time.'
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access | T1110 Brute Force |
Rule body kusto
id: 2238d13a-cf05-4973-a83f-d12a25dbb153
name: GitLab - Brute-force Attempts
description: |
'This query relies on GitLab Application Logs to get failed logins to highlight brute-force attempts from different IP addresses in a short space of time.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SyslogAma
dataTypes:
- Syslog
queryFrequency: 1h
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- CredentialAccess
relevantTechniques:
- T1110
query: |
let LearningPeriod = 7d;
let EndLearningTime = now();
let BinTime = 1h;
let RunTime = 1h;
let MinThreshold = 3.0;
let GitLabFailedLogins = (GitLabApp
| where FailedLogin == 1
| parse kind=regex Message with "Failed Login: username=" User "ip=" IpAddress
| project TimeGenerated, EventTime, Computer, User, HostName, HostIP, IpAddress);
GitLabFailedLogins
| where EventTime between (ago(LearningPeriod) .. EndLearningTime)
| summarize FailedLoginsCountInBinTime = count() by User, bin(EventTime, BinTime)
| summarize AvgOfFailedLoginsInLearning = avg(FailedLoginsCountInBinTime), StdOfFailedLoginsInLearning = stdev(FailedLoginsCountInBinTime) by User
| extend LearningThreshold = max_of(AvgOfFailedLoginsInLearning, MinThreshold)
| join kind=innerunique ( GitLabFailedLogins
| summarize FailedLoginsCountInRunTime = count() by User, IpAddress, EventTime = bin(EventTime, BinTime) ) on User
| where FailedLoginsCountInRunTime >= LearningThreshold
| project User, IpAddress, EventTime, FailedLoginsCountInRunTime, LearningThreshold
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPAddress
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: User
version: 1.0.1
kind: Scheduled
Stages and Predicates
Parameters
let LearningPeriod = 7d;
let EndLearningTime = now();
let BinTime = 1h;
let RunTime = 1h;
let MinThreshold = 3.0;
The stages below define let GitLabFailedLogins (the rule's main pipeline source).
Stage 1: source
GitLabApp
Stage 2: where
| where FailedLogin == 1
Stage 3: parse
| parse kind=regex Message with "Failed Login: username=" User "ip=" IpAddress
Stage 4: project
| project TimeGenerated, EventTime, Computer, User, HostName, HostIP, IpAddress
The stages below run on GitLabFailedLogins (the outer pipeline).
Stage 5: where
GitLabFailedLogins
| where EventTime between (ago(LearningPeriod) .. EndLearningTime)
Stage 6: summarize
| summarize FailedLoginsCountInBinTime = count() by User, bin(EventTime, BinTime)
Stage 7: summarize
| summarize AvgOfFailedLoginsInLearning = avg(FailedLoginsCountInBinTime), StdOfFailedLoginsInLearning = stdev(FailedLoginsCountInBinTime) by User
Stage 8: extend
| extend LearningThreshold = max_of(AvgOfFailedLoginsInLearning, MinThreshold)
Stage 9: join
| join kind=innerunique ( GitLabFailedLogins
| summarize FailedLoginsCountInRunTime = count() by User, IpAddress, EventTime = bin(EventTime, BinTime) ) on User
Stage 10: where
| where FailedLoginsCountInRunTime >= LearningThreshold
Stage 11: project
| project User, IpAddress, EventTime, FailedLoginsCountInRunTime, LearningThreshold
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
FailedLogin | eq |
|
FailedLoginsCountInRunTime | ge |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
EventTime | project |
FailedLoginsCountInRunTime | project |
IpAddress | project |
LearningThreshold | project |
User | project |