I'm currently building a detection that needs to extract data from one field and pass it to a variable to match events for that particular user over 30 days and add the user to the outcome section.
Essentially this rule should look for LDAP users who have not received vault temp credits over the last 30 days.
here's the error message
semantic analysis: match variable event is not assigned to an event field
rule auth0_anomaly_ldap_vault_creds {
events:
// Retrieve all Auth0 events regarding the issuance of vault temp creds for ldap users
$event.metadata.log_type = "AUTH_ZERO"
$event.principal.hostname = /^Temp Vault Client auth=ldap/
// Extract LDAP user
$ldap_user_extract = re.regex($event.principal.hostname, "auth=([^ ]+) expires")
$ldap_user = $ldap_user_extract
match:
$ldap_user over 30d
outcome:
// Alert Meta
$alert_severity = array_distinct("HIGH")
// Alert Details
$principal_ip = array_distinct($event.principal.ip)
$auth0_event_type = array_distinct($event.metadata.product_event_type)
$auth0_signup_email = array_distinct($event.additional.fields["email"])
$auth0_user_id = array_distinct($event.target.user.userid)
$auth0_user_full_name = array_distinct($event.principal.user.userid)
$user = array_distinct($ldap_user)
$network_org_name = array_distinct($event.principal.ip_geo_artifact.network.organization_name)
$source_state = array_distinct($event.principal.location.state)
$source_country = array_distinct($event.principal.location.country_or_region)
$user_agent = array_distinct($event.network.http.user_agent)
$referrer = array_distinct($event.network.http.referral_url)
$principal_ip_asn = array_distinct($event.principal.ip_geo_artifact.network.asn)
// Alert Risk Score
$risk_score = max(
// Base score for High Severity
75 +
// Increase Risk if SRE, CloudOps, or IT Support
if ( $event.principal.user.department = "IT Technical Operations", 20) +
if ( $event.principal.user.department = "IT Support", 10) +
// Increase Risk in cases of elevated Risk_Level (Okta Logs)
if ( $event.security_result.outcomes["Risk_Level"] = "MEDIUM" nocase, 10) +
if ( $event.security_result.outcomes["Risk_Level"] = "HIGH" nocase, 20) +
// Increase Risk if an Identity Threat is detected (Okta Logs)
if ( $event.security_result.outcomes["threatSuspected"] = "true" nocase, 10) +
// Increase Risk if user is an Admin or Delegated Admin
if ( $event.target.user.attribute.labels["is_admin"] = "true", 10) +
if ( $event.target.user.attribute.labels["is_delegated_admin"] = "true", 10)
)
condition:
$event
}
Solved! Go to Solution.
There are a couple of syntax issues here that I'd like to call out.
Line 9 is using the regex function which would be evaluating if the field contains a regex match to what you are looking for. It should not have a placeholder variable associated with it. I mean it could be you are getting a true/false, that is does it match or doesn't it.
Line 10 has a placeholder variable written to another placeholder variable which isn't allowed as match variables need to be associated with a field. I think in this specific area would want another line of criteria that is creating the $ldap_user placeholder variable but using the re.capture function to grab the value you want (which can then be used for the match variable).
Finally, the match variable accepts values over a 2 day window. The match is taking all events that meet the criteria in the events section and aggregates them based on the match variables(s) across a time range of 1 minute to 2 days.
Looking back over 30 days is more of a search function at the moment, though with some of the work we have underway, we may have some other ways to solve for things like this.
If you are looking for additional help on rule writing in Chronicle, here are some additional resources to assist.
Video shorts on tips when building rules: https://www.googlecloudcommunity.com/gc/Chronicle-Best-Practices/tkb-p/chronicle-best-practices
New to Chronicle Blog Series (new posts coming soon to SecOpsCommunity): https://chronicle.security/blog/?filters=new-to-chronicle-series
The maximum time window within a match statement is 48 hours, therefore creating a rule to detect this (if you are trying to capture an even extended period of time) is not currently feasible unfortunately.
However, if you are happy with matching over a 48 hour window, then this modification may work?
rule auth0_anomaly_ldap_vault_creds {
meta:
author = "Ayman C"
events:
// Retrieve all Auth0 events regarding the issuance of vault temp creds for ldap users
$event.metadata.log_type = "AUTH_ZERO"
$event.principal.hostname = /^Temp Vault Client auth=ldap/
// Extract LDAP user
$ldap_user_extract = re.capture($event.principal.hostname, "auth=([^ ]+) expires")
match:
$ldap_user_extract over 48h
outcome:
// Alert Meta
$alert_severity = array_distinct("HIGH")
// Alert Details
$principal_ip = array_distinct($event.principal.ip)
$auth0_event_type = array_distinct($event.metadata.product_event_type)
$auth0_signup_email = array_distinct($event.additional.fields["email"])
$auth0_user_id = array_distinct($event.target.user.userid)
$auth0_user_full_name = array_distinct($event.principal.user.userid)
$network_org_name = array_distinct($event.principal.ip_geo_artifact.network.organization_name)
$source_state = array_distinct($event.principal.location.state)
$source_country = array_distinct($event.principal.location.country_or_region)
$user_agent = array_distinct($event.network.http.user_agent)
$referrer = array_distinct($event.network.http.referral_url)
$principal_ip_asn = array_distinct($event.principal.ip_geo_artifact.network.asn)
// Alert Risk Score
$risk_score = max(
// Base score for High Severity
75 +
// Increase Risk if SRE, CloudOps, or IT Support
if ( $event.principal.user.department = "IT Technical Operations", 20) +
if ( $event.principal.user.department = "IT Support", 10) +
// Increase Risk in cases of elevated Risk_Level (Okta Logs)
if ( $event.security_result.outcomes["Risk_Level"] = "MEDIUM" nocase, 10) +
if ( $event.security_result.outcomes["Risk_Level"] = "HIGH" nocase, 20) +
// Increase Risk if an Identity Threat is detected (Okta Logs)
if ( $event.security_result.outcomes["threatSuspected"] = "true" nocase, 10) +
// Increase Risk if user is an Admin or Delegated Admin
if ( $event.target.user.attribute.labels["is_admin"] = "true", 10) +
if ( $event.target.user.attribute.labels["is_delegated_admin"] = "true", 10)
)
condition:
$event
}
I think the problem might be having the "$event" variable in the match section.
The event variables are not allowed in the match condition. Here in the above example, since the rule is triggered in a single event.
There are a couple of syntax issues here that I'd like to call out.
Line 9 is using the regex function which would be evaluating if the field contains a regex match to what you are looking for. It should not have a placeholder variable associated with it. I mean it could be you are getting a true/false, that is does it match or doesn't it.
Line 10 has a placeholder variable written to another placeholder variable which isn't allowed as match variables need to be associated with a field. I think in this specific area would want another line of criteria that is creating the $ldap_user placeholder variable but using the re.capture function to grab the value you want (which can then be used for the match variable).
Finally, the match variable accepts values over a 2 day window. The match is taking all events that meet the criteria in the events section and aggregates them based on the match variables(s) across a time range of 1 minute to 2 days.
Looking back over 30 days is more of a search function at the moment, though with some of the work we have underway, we may have some other ways to solve for things like this.
If you are looking for additional help on rule writing in Chronicle, here are some additional resources to assist.
Video shorts on tips when building rules: https://www.googlecloudcommunity.com/gc/Chronicle-Best-Practices/tkb-p/chronicle-best-practices
New to Chronicle Blog Series (new posts coming soon to SecOpsCommunity): https://chronicle.security/blog/?filters=new-to-chronicle-series
Thanks for the reply @jstoner
I'm trying to create an anomaly-based threat detection. The $event.principal.hostname full event looks like this "Temp Vault Client auth=ldap-exampleuser expires on: Jan 27 2024 20:17:49".
This variable $ldap_user_extract = re.regex($event.principal.hostname, "auth=([^ ]+) expires") is supposed to pull ldap-exampleuser from the event and pass it to the variable, in which it is supposed to check to see if this user has created an event in $event.principal.hostname within a certain amount of days. If a user has triggered the alert after a certain amount of days I would like to be notified.
Is this possible in chronicle ?
The maximum time window within a match statement is 48 hours, therefore creating a rule to detect this (if you are trying to capture an even extended period of time) is not currently feasible unfortunately.
However, if you are happy with matching over a 48 hour window, then this modification may work?
rule auth0_anomaly_ldap_vault_creds {
meta:
author = "Ayman C"
events:
// Retrieve all Auth0 events regarding the issuance of vault temp creds for ldap users
$event.metadata.log_type = "AUTH_ZERO"
$event.principal.hostname = /^Temp Vault Client auth=ldap/
// Extract LDAP user
$ldap_user_extract = re.capture($event.principal.hostname, "auth=([^ ]+) expires")
match:
$ldap_user_extract over 48h
outcome:
// Alert Meta
$alert_severity = array_distinct("HIGH")
// Alert Details
$principal_ip = array_distinct($event.principal.ip)
$auth0_event_type = array_distinct($event.metadata.product_event_type)
$auth0_signup_email = array_distinct($event.additional.fields["email"])
$auth0_user_id = array_distinct($event.target.user.userid)
$auth0_user_full_name = array_distinct($event.principal.user.userid)
$network_org_name = array_distinct($event.principal.ip_geo_artifact.network.organization_name)
$source_state = array_distinct($event.principal.location.state)
$source_country = array_distinct($event.principal.location.country_or_region)
$user_agent = array_distinct($event.network.http.user_agent)
$referrer = array_distinct($event.network.http.referral_url)
$principal_ip_asn = array_distinct($event.principal.ip_geo_artifact.network.asn)
// Alert Risk Score
$risk_score = max(
// Base score for High Severity
75 +
// Increase Risk if SRE, CloudOps, or IT Support
if ( $event.principal.user.department = "IT Technical Operations", 20) +
if ( $event.principal.user.department = "IT Support", 10) +
// Increase Risk in cases of elevated Risk_Level (Okta Logs)
if ( $event.security_result.outcomes["Risk_Level"] = "MEDIUM" nocase, 10) +
if ( $event.security_result.outcomes["Risk_Level"] = "HIGH" nocase, 20) +
// Increase Risk if an Identity Threat is detected (Okta Logs)
if ( $event.security_result.outcomes["threatSuspected"] = "true" nocase, 10) +
// Increase Risk if user is an Admin or Delegated Admin
if ( $event.target.user.attribute.labels["is_admin"] = "true", 10) +
if ( $event.target.user.attribute.labels["is_delegated_admin"] = "true", 10)
)
condition:
$event
}
Thanks, I assumed that this wouldnt be possible. I looked into the context awareness feature and didnt seem to be helpful either