KQL Validations for Multiple data sources hunting queries

This commit is contained in:
DixitVedanshi 2023-02-08 11:25:45 +05:30
Родитель cd2e105f2e
Коммит 758d70b09e
18 изменённых файлов: 37 добавлений и 125 удалений

Просмотреть файл

@ -2365,11 +2365,6 @@
"templateName": "ZscalerIPsByPorts.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "33aa0e01-87e2-43ea-87f9-2f7e3ff1d532",
"templateName": "WireDataBeacon.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "ab8b5893-0c82-4a8c-ae19-43669b3d1eba",
"templateName": "VulnComputers.yaml",
@ -2450,21 +2445,6 @@
"templateName": "UseragentExploitPentest.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "f56b2223-0d4d-4347-9de4-822d195624ee",
"templateName": "UserAccounts-UnusualLogonTimes.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "8eace93b-f38c-47b7-a21d-739556d31db6",
"templateName": "UserAccounts-NewSingleFactorAuth.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "dbc82bc1-c7df-44e3-838a-5846a313cf35",
"templateName": "UserAccounts-BlockedAccounts.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "f18c4dfb-4fa6-4a9d-9bd3-f7569d1d685a",
"templateName": "User Grant Access and Grants Other Access.yaml",
@ -2495,21 +2475,11 @@
"templateName": "UnicodeObfuscationInCommandLine.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "6962473c-bcb8-421d-a0db-826078cad280",
"templateName": "UnfamiliarsignincorrelationwithPortalSigninandAuditlogs.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "5bf4b982-a9e6-4877-b2c0-bdbe4d0f27db",
"templateName": "UbiquitiUnusualSubdomains.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "431cccd3-2dff-46ee-b34b-61933e45f556",
"templateName": "TrackingPrivAccounts.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "506955be-648f-11ec-90d6-0242ac120003",
"templateName": "TMApexOneSpywareDetection.yaml",
@ -2540,11 +2510,6 @@
"templateName": "SuspiciousUrlClicked.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "bc17381e-07ee-48a2-931f-06a3d9e149c9",
"templateName": "SuccessThenFail_SameUserDiffApp.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "3c82774a-df78-44eb-9ab3-13ef37c63ae4",
"templateName": "Sticky Keys.yaml",
@ -2655,21 +2620,6 @@
"templateName": "RareMFAOperation.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "66fb97d1-55c3-4268-ac22-b9742d0fdccc",
"templateName": "RareDomainsInCloudLogs.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "06c52a66-fffe-4d3b-a05a-646ff65b7ec2",
"templateName": "RareDNSLookupWithDataTransfer.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "a787a819-40df-4c9f-a5ae-850d5a2a0cf6",
"templateName": "RareClientFileAccess.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "f4506828-36f5-4668-8203-de062963be63",
"templateName": "Ransomware hits healthcare - Possible compromised accounts.yaml",
@ -2695,11 +2645,6 @@
"templateName": "ProofpointPODLargeOutboundEmails.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "97ff9459-dade-404a-b90e-d93b9acde1a4",
"templateName": "PotentialProcessDoppelganging.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "95db9b9c-7a12-4c0b-85c8-1c54f67c5ac7",
"templateName": "Potential ransomware activity related to Cobalt Strike.yaml",
@ -2875,16 +2820,6 @@
"templateName": "MD AV Signature and Platform Version.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "3d217bb4-9cc2-4aba-838a-48e606e910e6",
"templateName": "LowAndSlowPasswordAttempt.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "562900b1-39c4-4baf-a050-9cad1641db35",
"templateName": "LogonwithExpiredAccount.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "44a5c680-d2ac-4bed-8210-c3aafea47308",
"templateName": "logon-attempts-after-malicious-email.yaml",
@ -2990,11 +2925,6 @@
"templateName": "HuntingQuery-AffectedRowAnomaly.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "4a6030de-c11c-4206-b4ea-cd005ebf80a2",
"templateName": "hunt_LOLBins.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "79cf4646-0959-442f-9707-60fc66eb8145",
"templateName": "HighCPURoom.yaml",
@ -3270,16 +3200,6 @@
"templateName": "Anomalous Device Models.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "11d808a1-32fe-4618-946a-cfd43523347a",
"templateName": "AlertsWithFile.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "61a6edc0-e71a-4084-8f3c-05a58e1b9012",
"templateName": "AlertsOnHost.yaml",
"validationFailReason": "Temporarily Added for Hunting Query validation"
},
{
"id": "ef76733a-86ab-4592-b341-64a4b369f4b7",
"templateName": "Alerts related to Log4j vulnerability.yaml",

Просмотреть файл

@ -62,7 +62,7 @@ query: |
case(
ResultType == '50057', 'SigninLogs( Result Code- 50057) - User account is disabled. The account has been disabled by an administrator.',
'Unknown'), Account = UserPrincipalName
| project Computer, Account, Reason , TimeGenerated
| project Account, Reason , TimeGenerated
) )
| summarize StartTimeUtc = min(TimeGenerated), EndTImeUtc = max(TimeGenerated), EventCount = count() by Computer, Account, Reason
| extend timestamp = StartTimeUtc, AccountCustomEntity = Account, HostCustomEntity = Computer

Просмотреть файл

@ -34,7 +34,7 @@ query: |
),
(imProcessCreate
| where ParentProcessName endswith "diawp.exe" or ParentProcessName endswith "ReportingServicesService.exe" or ParentProcessName endswith "RSPortal.exe" or ParentProcessName endswith "RsPowerBI.exe" or ParentProcessName endswith "taskexecutor.exe"
| where ActingProcessName = "cmd.exe"
| where ActingProcessName == "cmd.exe"
| where (CommandLine has_any (cmdline_tokens))
| extend timestamp = TimeGenerated, HostCustomEntity = DvcHostname , AccountCustomEntity = ActorUsername, ProcessCustomEntity = TargetProcessFilePath
),

Просмотреть файл

@ -82,19 +82,9 @@ query: |
| extend IPCustomEntity = DestinationIP
| sort by sum_SentBytes desc
),
(WireData
| where TimeGenerated between(starttime..endtime)
| where Direction == "Outbound"
| where ipv4_is_private(RemoteIP) == false
| project DataType = Type, TimeGenerated , SourceIP = LocalIP , SourcePort = LocalPortNumber , DestinationIP = RemoteIP, DestinationPort = RemotePortNumber, ReceivedBytes, SentBytes
| summarize sum(ReceivedBytes), sum(SentBytes), ConnectionCount = count() by DataType, SourceIP, SourcePort, DestinationIP, DestinationPort
| extend IPCustomEntity = DestinationIP
| extend DataType = Type
| sort by sum_SentBytes desc
),
(VMConnection
| where TimeGenerated between(starttime..endtime)
| where Direction == "outbound"
| where Direction == "Outbound"
| where ipv4_is_private(DestinationIp) == false
| project DataType = Type, TimeGenerated, SourceIP = SourceIp , DestinationIP = DestinationIp, DestinationPort, ReceivedBytes = BytesReceived, SentBytes = BytesSent
| summarize sum(ReceivedBytes), sum(SentBytes), ConnectionCount = count() by DataType, SourceIP, DestinationIP, DestinationPort

Просмотреть файл

@ -40,7 +40,7 @@ query: |
| where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY"
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))
| where isnotempty(RareDomain)
| summarize RareDomainCount = count() by Type, RareDomain
| summarize RareDomainCount = count() by Type, RareDomain,UserPrincipalName
| where RareDomainCount <= domainLimit
| extend AccountCustomEntity = UserPrincipalName
// remove comment from below if you would like to have a lower limit for RareDomainCount specific to AuditLog
@ -50,7 +50,7 @@ query: |
| extend UserPrincipalName = tolower(UserId)
| where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY"
| extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1]))
| summarize RareDomainCount = count() by Type, RareDomain
| summarize RareDomainCount = count() by Type, RareDomain, UserPrincipalName
| where RareDomainCount <= domainLimit
| extend AccountCustomEntity = UserPrincipalName
// remove comment from below if you would like to have a lower limit for RareDomainCount specific to OfficeActivity

Просмотреть файл

@ -32,8 +32,6 @@ relevantTechniques:
- T1078
- T1087
query: |
let LocalSID = "S-1-5-32-5[0-9][0-9]$";
let GroupSID = "S-1-5-21-[0-9]*-[0-9]*-[0-9]*-5[0-9][0-9]$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1102$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1103$";
let p_Accounts = SecurityEvent
@ -63,14 +61,16 @@ query: |
(SigninLogs
| where TimeGenerated >= a_StartTime and TimeGenerated <= a_EndTime
| extend AccountName = tolower(split(UserPrincipalName, "@")[0]), WinSecEventDomain = "-"
| project-rename EventType = strcat(OperationName, "-", ResultType, "-", ResultDescription), ServiceOrSystem = AppDisplayName, ClientIP = IPAddress)
| extend Event = strcat("OperationName", "-", "ResultType", "-", "ResultDescription")
| project-rename EventType = Event, ServiceOrSystem = AppDisplayName, ClientIP = IPAddress)
on AccountName),
(AccountFormat | join kind=inner
(OfficeActivity
| where TimeGenerated >= a_StartTime and TimeGenerated <= a_EndTime
| extend AccountName = tolower(split(UserId, "@")[0]), WinSecEventDomain = "-"
| project-rename EventType = strcat(Operation, "-", ResultStatus), ServiceOrSystem = OfficeWorkload)
on AccountName),
| extend Event = strcat(Operation, "-", ResultStatus)
| project-rename EventType = Event, ServiceOrSystem = OfficeWorkload)
on AccountName),
(AccountFormat | join kind=inner
(SecurityEvent
| where TimeGenerated >= a_StartTime and TimeGenerated <= a_EndTime
@ -119,13 +119,13 @@ query: |
rel_Count = count() by AccountName = tolower(UserId), rel_EventType = Operation, Type
) on AccountName),
(ra_Today | join kind=inner
(SecurityEvent | where TimeGenerated > LastDay
(SecurityEvent | where TimeGenerated > LastDay
| where EventID in (4624, 4625)
| where AccountType == "User"
| summarize rel_StartTime = min(TimeGenerated), rel_EndTime = max(TimeGenerated), rel_ServiceOrSystemCount = dcount(Computer),
rel_ServiceOrSystemSet = makeset(Computer), rel_ClientIPSet = makeset("-"),
rel_Count = count() by DomainSlashAccount = tolower(Account), rel_EventType = Activity, Type
) on DomainSlashAccount),
rel_Count = count() by DomainSlashAccount = tolower(Account), rel_EventType = Activity, Type, AccountName
) on AccountName),
(ra_Today | join kind=inner
(Event | where TimeGenerated > LastDay
// 7045: A service was installed in the system
@ -133,15 +133,15 @@ query: |
| summarize rel_StartTime = min(TimeGenerated), rel_EndTime = max(TimeGenerated), rel_ServiceOrSystemCount = dcount(Computer),
rel_ServiceOrSystemSet = makeset(Computer), rel_ClientIPSet = makeset("-"),
rel_Count = count() by DomainSlashAccount = tolower(UserName), rel_EventType = strcat(EventID, "-", tostring(split(RenderedDescription,".")[0])), Type
) on DomainSlashAccount),
) on $left.AccountName == $right.DomainSlashAccount),
(ra_Today | join kind=inner
(SecurityEvent | where TimeGenerated > LastDay
// 4720: Account created, 4726: Account deleted
| where EventID in (4720,4726)
| summarize rel_StartTime = min(TimeGenerated), rel_EndTime = max(TimeGenerated), rel_ServiceOrSystemCount = dcount(UserPrincipalName),
rel_ServiceOrSystemSet = makeset(UserPrincipalName), rel_ClientIPSet = makeset("-"),
rel_Count = count() by DomainSlashAccount = tolower(Account), rel_EventType = Activity, Type
) on DomainSlashAccount),
rel_Count = count() by DomainSlashAccount = tolower(Account), rel_EventType = Activity, Type, AccountName
) on AccountName),
(ra_Today | join kind=inner
(SigninLogs | where TimeGenerated > LastDay
| extend RemoteHost = tolower(tostring(parse_json(DeviceDetail.["displayName"])))
@ -150,8 +150,8 @@ query: |
| summarize rel_StartTime = min(TimeGenerated), rel_EndTime = max(TimeGenerated), a_RelatedRemoteHostSet = makeset(RemoteHost),
rel_ServiceOrSystemSet = makeset(AppDisplayName), rel_ServiceOrSystemCount = dcount(AppDisplayName), rel_ClientIPSet = makeset(IPAddress),
rel_StateSet = makeset(State),
rel_Count = count() by AccountAtDomain = tolower(UserPrincipalName), rel_EventType = iff(isnotempty(ResultDescription), ResultDescription, StatusDetails), Type
) on AccountAtDomain),
rel_Count = count() by AccountAtDomain = tolower(UserPrincipalName), rel_EventType = iff(isnotempty(ResultDescription), ResultDescription, StatusDetails), Type)
on $left.WinSecEventDomain == $right.AccountAtDomain),
(ra_Today | join kind=inner
(AWSCloudTrail | where TimeGenerated > LastDay
| summarize rel_StartTime = min(TimeGenerated),rel_EndTime = max(TimeGenerated), rel_ServiceOrSystemSet = makeset(EventSource),
@ -164,8 +164,8 @@ query: |
| extend AccountName = tostring(ExtProps.["user name"])
| summarize rel_StartTime = min(TimeGenerated), rel_EndTime = max(TimeGenerated), rel_ServiceOrSystemCount = dcount(AlertType),
rel_ServiceOrSystemSet = makeset(AlertType),
rel_Count = count() by DomainSlashAccount = tolower(AccountName), rel_EventType = ProductName, Type
) on DomainSlashAccount)
rel_Count = count() by DomainSlashAccount = tolower(AccountName), rel_EventType = ProductName, Type, AccountName)
on AccountName)
);
a_Related
| project Type, RareActivtyStartTimeUtc = ra_StartTime, RareActivityEndTimeUtc = ra_EndTime, RareActivityCount = ra_Count,

Просмотреть файл

@ -64,7 +64,7 @@ query: |
| project InitiatedBy = tolower(InitiatedBy), ActivityDateTime, ActivityDisplayName,IpAddress, AADOperationType, AADTenantId
) on $left.AccountCustomEntity == $right.InitiatedBy
| project AccountCustomEntity,AppDisplayName,IPAddress,Location,StatusCode,StatusDetails
entityMappings:
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address

Просмотреть файл

@ -22,10 +22,10 @@ query: |
let v_EndTime = suspiciousEventTime+6h;
SecurityAlert
| where TimeGenerated between (v_StartTime .. v_EndTime)
| where Computer contains v_Host
// expand JSON properties
| extend Extprop = parse_json(ExtendedProperties)
| extend Computer = iff(isnotempty(toupper(tostring(Extprop["Compromised Host"]))), toupper(tostring(Extprop["Compromised Host"])), tostring(parse_json(Entities)[0].HostName))
| where Computer contains v_Host
| extend Account = iff(isnotempty(tolower(tostring(Extprop["User Name"]))), tolower(tostring(Extprop["User Name"])), tolower(tostring(Extprop["user name"])))
| extend IpAddress = tostring(parse_json(ExtendedProperties).["Client Address"])
| project TimeGenerated, AlertName, Computer, Account, IpAddress, ExtendedProperties

Просмотреть файл

@ -22,6 +22,8 @@ query: |
SecurityAlert
| where TimeGenerated between (v_StartTime .. v_EndTime)
| where ExtendedProperties has v_File
// expand JSON properties
| extend Extprop = parse_json(ExtendedProperties)
| extend Computer = iff(isnotempty(toupper(tostring(Extprop["Compromised Host"]))), toupper(tostring(Extprop["Compromised Host"])), tostring(parse_json(Entities)[0].HostName))
| extend Account = iff(isnotempty(tolower(tostring(Extprop["User Name"]))), tolower(tostring(Extprop["User Name"])), tolower(tostring(Extprop["user name"])))
| extend IpAddress = tostring(parse_json(ExtendedProperties).["Client Address"])

Просмотреть файл

@ -13,7 +13,7 @@ relevantTechniques:
- T1055.013
query: |
// Enter a reference list of trusted processes
let TrustedProcessList = dynamic ([ "c:\\windows\\system32\\svchost.exe","c:\\windows\\system32\\lsass.exe","c:\\windows\\servicing\\TrustedInstaller.exe","c:\\windows\\system32\\poqexec.exe","TiWorker.exe","C:\\Windows\\System32\\inetsrv\\appcmd.exe","C:\\Windows\\System32\\inetsrv\\InetMgr.exe","C:\\Windows\\System32\\wsmprovhost.exe","C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\Enterprise\\Common7\\IDE\\devenv.exe"]);
let TrustedProcessList = dynamic (["c:\\windows\\system32\\svchost.exe","c:\\windows\\system32\\lsass.exe","c:\\windows\\servicing\\TrustedInstaller.exe","c:\\windows\\system32\\poqexec.exe","TiWorker.exe","C:\\Windows\\System32\\inetsrv\\appcmd.exe","C:\\Windows\\System32\\inetsrv\\InetMgr.exe","C:\\Windows\\System32\\wsmprovhost.exe","C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\IDE\\devenv.exe"]);
SecurityEvent
| where EventID == 4985 and not (ProcessName has_any (TrustedProcessList)) and SubjectLogonId !="0x3e7"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by EventID, Computer, ProcessName, SubjectUserName

Просмотреть файл

@ -23,6 +23,6 @@ query: |
| where SubjectUserName != "SYSTEM"
| where ParentProcessName has_any (Bin)
// Looking to only include details of those that have command line activities matching 1 or more of the defined IOCs
| where ProcessCommandLine has_any (ioc)
| project TimeGenerated, SubjectMachineName, SubjectUserName, ParentProcessName, Process, ProcessCommandLine
| where CommandLine has_any (ioc)
| project TimeGenerated, SubjectMachineName, SubjectUserName, ParentProcessName, Process, CommandLine
| sort by TimeGenerated asc

Просмотреть файл

@ -65,7 +65,7 @@ query: |
// The below line can be removed if the actor is using IPs in one country
| where UnsuccessfulLoginCountryCount > UnsuccessfulLoginCountryThreshold
| project StartTime, EndTime, UserPrincipalName, Failures, IPs, DaysWithAttempts, UnsuccessfulLoginCountryCount, UnuccessfulLoginCountries=IPAddressLocations, SuccessfulLoginCountries, FailureIPAddresses=IPAddresses
| extend timestamp = StartTime, AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddresses
| extend timestamp = StartTime, AccountCustomEntity = UserPrincipalName, IPCustomEntity = FailureIPAddresses
entityMappings:
- entityType: Account
fieldMappings:

Просмотреть файл

@ -38,7 +38,7 @@ query: |
// Only take hits where there is 5 or less distinct AppDisplayNames on the success side as this limits highly active applications where failures occur more regularly
let Distribution =
InitialDataSet
| summarize count(SuccessAppDisplayName) by SuccessAppDisplayName, ResultType
| summarize count_SuccessAppDisplayName = count() by SuccessAppDisplayName, ResultType
| where count_SuccessAppDisplayName <= 5;
InitialHits | join (
Distribution

Просмотреть файл

@ -18,8 +18,8 @@ tags:
- AADSecOpsGuide
query: |
let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let starttime = timespan('{{StartTimeISO}}');
let endtime = timespan('{{EndTimeISO}}');
let lookback = starttime - 7d;
let isGUID = "[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}";
let aadFunc = (tableName:string){

Просмотреть файл

@ -18,8 +18,8 @@ tags:
- AADSecOpsGuide
query: |
let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let starttime = timespan('{{StartTimeISO}}');
let endtime = timespan('{{EndTimeISO}}');
let isGUID = "[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}";
let lookback = starttime - 7d;
let aadFunc = (tableName:string){

Просмотреть файл

@ -15,8 +15,8 @@ tags:
- AADSecOpsGuide
query: |
let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let starttime = timespan('{{StartTimeISO}}');
let endtime = timespan('{{EndTimeISO}}');
let isGUID = "[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}";
let userthreshold = 25;
let HistLogons = SigninLogs

Просмотреть файл

@ -26,7 +26,7 @@ query: |
|where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
// excluded internal web page
|where ipv4_is_private(sIP) == false
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), makelist(cIP), count(TimeGenerated) by csUriStem, sSiteName, csUserAgent;
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), makelist(cIP), dcount(TimeGenerated) by csUriStem, sSiteName, csUserAgent;
data
| mvexpand list_cIP
| distinct StartTime, EndTime, tostring(list_cIP), csUriStem, sSiteName, csUserAgent

Просмотреть файл

@ -23,7 +23,7 @@ query: |
let TotalEventsThreshold = 15;
let PercentBeaconThreshold = 95;
WireData
| where TimeGenerated > lookback
| where TimeGenerated > ago(lookback)
| where ipv4_is_private(RemoteIP) == false
| project TimeGenerated , LocalIP , LocalPortNumber , RemoteIP, RemotePortNumber, ReceivedBytes, SentBytes
| sort by LocalIP asc,TimeGenerated asc, RemoteIP asc, RemotePortNumber asc