Azure-Sentinel/Tools/RuleMigration/Rule Logic Mappings.md

19 KiB

Sample Rule Mapping between ArcSight/QRadar and Azure Sentinel


ArcSight


No. Type Sample Detection Rule Sample KQL Reference
1. Filter (and)
SecurityEvent
| where EventID == 4728
| where SubjectUserName =~ "AutoMatedService"
| where isnotempty(SubjectDomainName)
This assumes that the Windows Security Events are collected via MMA/AMA.
Hence, we are using SecurityEvent table in Azure Sentinel.

Note:
- Avoid case-insensitive operators (=~) when possible for query optimization.
- Use (==) if the value is not case-sensitive.
- Order the filters by starting with the 'where' statement that filter out the most data.

- String Operators
- Numerical Operators
- ago
- Datetime
- between
- now
- parse
- extract
- parse_json
- parse_csv
- parse_path
- parse_url
2. Filter (or) Option 1: Use 'in'
SecurityEvent
| where SubjectUserName in
("Adm1","ServiceAccount1","AutomationServices")

Option 2: Use 'or'
SecurityEvent
| where SubjectUserName == "Adm1" or
SubjectUserName == "ServiceAccount1" or
SubjectUserName == "AutomationServices"
Note:
Both options are identical in performance, but Option 1 is preferred as it is more user-readable.

- String Operators
- in
3. Nested Filter


"/All Filters/Soc Filters/Exclude Valid Users":

Option 1: Direct filter with "where" statement

SecurityEvent
| where EventID == 4728
| where isnotempty(SubjectDomainName) or
isnotempty(TargetDomainName)
| where SubjectUserName !~ "AutoMatedService"


Option 2: Use KQL function

1. Save the following query as KQL function with the alias of "ExcludeValidUsers".
SecurityEvent
| where EventID == 4728
| where isnotempty(SubjectDomainName)
| where SubjectUserName =~ "AutoMatedService"
| project SubjectUserName
2. After that, use the following query to filter "ExcludeValidUsers"
SecurityEvent
| where EventID == 4728
| where isnotempty(SubjectDomainName) or
isnotempty(TargetDomainName)
| where SubjectUserName !in (ExcludeValidUsers)

Option 3: Use parameter function

1. Create a parameter function with the name and alias of “ExcludeValidUsers”.
2. Define the parameters of the function. For example,
Tbl: (TimeGenerated:datatime, Computer:string, 
EventID:string, SubjectDomainName:string,
TargetDomainName:string, SubjectUserName:string)
3. The parameter function has the following query:
Tbl
| where SubjectUserName !~ "AutoMatedService"
4. Invoke the parameter function with the following query:
let Events = (
SecurityEvent
| where EventID == 4728
);
ExcludeValidUsers(Events)

Option 4: Use Join

Least preferred option. Avoid using 'join' when it can be done with other options.
let events = (
SecurityEvent
| where EventID == 4728
| where isnotempty(SubjectDomainName)
or isnotempty(TargetDomainName)
);
let ExcludeValidUsers = (
SecurityEvent
| where EventID == 4728
| where isnotempty(SubjectDomainName)
| where SubjectUserName =~ "AutoMatedService"
);
events
| join kind=leftanti ExcludeValidUsers on
$left.SubjectUserName == $right.SubjectUserName

Note:
- Avoid case-insensitive operators (=~ and !~) when possible for query optimization. Use (== and !=) if the value is not case-sensitive.
- Option 1 is preferred due to its simplicity while Option 4 is the least preferred option. Avoid using 'join' when it can be done with other options for better performance.

- Sample KQL function.
- Sample Parameter function.
- Join
- where
4. Active list (Lookup) This assumes the Watchlist 'Cyber-Ark Exception Accounts' has been created in Azure Sentinel with an 'Account' field.

let Activelist=(
_GetWatchlist('Cyber-Ark Exception Accounts')
| project Account );
CommonSecurityLog
| where DestinationUserName in (Activelist)
| where DeviceVendor == "Cyber-Ark"
| where DeviceAction == "Get File Request"
| where DeviceCustomNumber1 != ""
| project DeviceAction, DestinationUserName,
TimeGenerated,SourceHostName,
SourceUserName, DeviceEventClassID
Note:
Order the filters by starting with the 'where' statement that filter out the most data.
Watchlist is the "Active list" equivalent feature in Azure Sentinel.
Learn more about Watchlist with the following link:
- Watchlist

Watchlist is just one of the methods to implement lookups.
Refer to the below blog post for more options:
- Implementing Lookups in Azure Sentinel
5. Correlation
(Match a rule condition against a set of base events)
let event1 =(
SecurityEvent
| where EventID == 4728
);
let event2 =(
SecurityEvent
| where EventID == 4729
);
event1
| join kind=inner event2
on $left.TargetUserName==$right.TargetUserName
Note:
For optimization, make sure the smaller table is on the left side of the join. Also, if the left side is relatively small (up to 100K records), add hint.strategy=broadcast for better performance.
Join:
- Join
- Time Window Join
- Shuffle
- Broadcast
- Union

Define statement:
- let

Aggregation:
- make_set
- make_list
- make_bag
- pack
6. Correlation (Time Window Filter)
let waittime = 10m;
let lookback = 1d;
let event1 = (
SecurityEvent
| where TimeGenerated > ago(waittime+lookback)
| where EventID == 4728
| project event1_time = TimeGenerated,
event1_ID = EventID, event1_Activity= Activity,
event1_Host = Computer, TargetUserName,
event1_UPN=UserPrincipalName,
AccountUsedToAdd = SubjectUserName
);
let event2 = (
SecurityEvent
| where TimeGenerated > ago(waittime)
| where EventID == 4729
| project event2_time = TimeGenerated,
event2_ID = EventID, event2_Activity= Activity,
event2_Host= Computer, TargetUserName,
event2_UPN=UserPrincipalName,
AccountUsedToRemove = SubjectUserName
);
event1
| join kind=inner event2 on TargetUserName
| where event2_time - event1_time < lookback
| where tolong(event2_time - event1_time ) >=0
| project delta_time = event2_time - event1_time,
event1_time, event2_time,
event1_ID,event2_ID,event1_Activity,
event2_Activity, TargetUserName, AccountUsedToAdd,
AccountUsedToRemove,event1_Host,event2_Host,
event1_UPN,event2_UPN
- Join
- Azure Sentinel Correlation Rules : Join
7. Aggregation
SecurityEvent
| summarize Count = count() by SubjectUserName,
SubjectDomainName
| where Count >3
- summarize




QRadar


No. Type Sample Detection Rule Sample KQL Reference
1. Common Property Tests Syntax: See below for each statement separately:
and when any of <these properties> match <this regular expression>
Example:
CommonSecurityLog
| where tostring(SourcePort)
matches regex @"\d{1,5}"
or tostring(DestinationPort)
matches regex @"\d{1,5}"
- matches
regex
and when the event matches <this> AQL filter query
Example:
CommonSecurityLog
| where SourceIP == '10.1.1.10'
- String Operators
and when <this property> <equals/not equals> <this property>
Example:
CommonSecurityLog
| where SourceIP == DestinationIP
- String Operators
2. Date/Time Tests Syntax: See below for each statement separately: - Date/time operations
and when the event(s) occur <on/after/before> the <selected> day of the month
Example:
SecurityEvent
| where dayofmonth(TimeGenerated)<4
- dayofmonth()
and when the event(s) occur on any of <these days of the week{Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}>
Example:
SecurityEvent
| where dayofweek(TimeGenerated)
between (3d .. 5d)
- dayofweek()
and when the event(s) occur <after/before/at> <this time{12.00AM, 12.05AM, ...11.50PM, 11.55PM}>
Example:
SecurityEvent
| where format_datetime(TimeGenerated,
'HH:mm')=="23:55"
Note: TimeGenerated is in UTC/GMT
- format_
datetime
3. Event property Tests See below for each statement separately:
and when the IP protocol is one of the following <protocols>
Example:
CommonSecurityLog
| where Protocol in ("UDP","ICMP")
- String Operators
and when the Event Payload contains <this string>
Example:
CommonSecurityLog
| where DeviceVendor has "Palo Alto"
Note:
Avoid using "search()" command if you already know the table name as it is not performance optimized.
- has
4. Functions - Counters See below for each statement separately:
and when at least <this many> events are seen with the same <event properties> in <this many> <minutes>
Example:
CommonSecurityLog
| summarize Count = count()
by SourceIP, DestinationIP
| where Count >= 5
- summarize
5. Functions - Negative See below for each statement separately:
and when none of <these rules> match in <this many> <minutes> after <these rules> match with the same <event properties>
Example: Example using the rules defined above:
let spanoftime = 10m;
let Test2 = (
CommonSecurityLog
| where Protocol !in ("UDP","ICMP")
| where TimeGenerated >
ago(spanoftime)
);
let Test6 = (
CommonSecurityLog
| where SourceIP == DestinationIP
);
Test2
| join kind=rightanti Test6 on
$left.SourceIP == $right.SourceIP
and $left.Protocol ==$right.Protocol
- join()
- String Operators
- Numerical Operators
6. Functions – Simple See below for each statement separately:
and when an event matches <any|all> of the following <rules>
Example:
CommonSecurityLog
| where Protocol !in ("UDP","ICMP")
or SourceIP == DestinationIP
- or
7. IP / Port Tests See below for each statement separately:
and when the source port is one of the following <ports>
Example:
CommonSecurityLog
| where SourcePort == 20
- String Operators
and when the source IP is one of the following <IP addresses>
Example:
CommonSecurityLog
| where SourceIP in
("10.1.1.1","10.2.2.2")
- String Operators
8. Log Source Tests See below for each statement separately:
and when the event(s) were detected by one or more of these <log source types>
Example:
OfficeActivity
| where OfficeWorkload == "Exchange"
- String Operators