Detection rules › Kusto

GitHub Activites from a New Country

Status
available
Severity
medium
Time window
7d
Group by
Actor
Source
github.com/Azure/Azure-Sentinel

'Detect activities from a location that was not recently or was never visited by the user or by any user in your organization.'

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Rule body

id: f041e01d-840d-43da-95c8-4188f6cef546
name: GitHub Activites from a New Country
description: |
  'Detect activities from a location that was not recently or was never visited by the user or by any user in your organization.'
severity: Medium
status: Available
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1078
query: |
  let LearningPeriod = 7d;
  let RunTime = 1h;
  let StartTime = 1h;
  let EndRunTime = StartTime - RunTime;
  let EndLearningTime = StartTime + LearningPeriod;
  let GitHubCountryCodeLogs = (GitHubAuditData
  | where Country != "");
    GitHubCountryCodeLogs
  | where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
  | summarize makeset(Country) by Actor
  | join kind=innerunique (
    GitHubCountryCodeLogs
    | where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
    | distinct Country, Actor, TimeGenerated
  ) on Actor 
  | where set_Country !contains Country
  | extend timestamp = TimeGenerated
  | extend AccountName = tostring(split(Actor, "@")[0]), AccountUPNSuffix = tostring(split(Actor, "@")[1])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: Actor
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
version: 1.0.1
kind: Scheduled

Stages and Predicates

Parameters

let LearningPeriod = 7d;
let RunTime = 1h;
let StartTime = 1h;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;

let GitHubCountryCodeLogs is inlined into the numbered stages below.

Stages 1 to 2 define let GitHubCountryCodeLogs (the rule's main pipeline source); stages 3 to 8 run on it.

Stage 1: source

GitHubAuditData

Stage 2: where

| where Country != ""

Stage 3: where

GitHubCountryCodeLogs
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))

Stage 4: summarize

| summarize makeset(Country) by Actor

Stage 5: join

| join kind=innerunique (
  GitHubCountryCodeLogs
  | where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
  | distinct Country, Actor, TimeGenerated
) on Actor

Stage 6: where

| where set_Country !contains Country

Stage 7: extend

| extend timestamp = TimeGenerated

Stage 8: extend

| extend AccountName = tostring(split(Actor, "@")[0]), AccountUPNSuffix = tostring(split(Actor, "@")[1])

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
set_Countrycross_field_compare
  • Country transforms: op:not_contains
field:"set_Country" kind:cross_field_compare value:"Country"

Output fields

These fields are emitted when the rule matches.

FieldSource
Actorsummarize
timestampextend
AccountNameextend
AccountUPNSuffixextend