תחביר של קטע תוצאות

נתמך ב:

בקטע outcome של שאילתת YARA-L מוגדרים משתני תוצאה שמציינים את הפלט של שאילתת חיפוש ושל שאילתת לוח בקרה, וגם הקשר ומידע נוספים לזיהוי כשמופעל כלל. אפשר להשתמש במשתנים האלה למטרות שונות, כמו הצגת נתונים רלוונטיים בלוחות בקרה ויצירת ציוני סיכון.

הגדרת קטע התוצאה

כדי להגדיר משתנה של תוצאה בקטע outcome של שאילתה יחידה, משתמשים בתו $ ואחריו שם המשתנה. אפשר להגדיר עד 20 משתני תוצאה. השמות של המשתנים הם שרירותיים. במקרה של כללים, ערכי התוצאות מחושבים ומצטברים על סמך כל זיהוי.

לכל משתנה של תוצאה מוקצה ערך באמצעות ביטוי.

הכלל הזה מחפש ניסיונות כניסה שנכשלו ממיקום חדש:

rule failed_logins
{
  meta:
   author = "Security Team"
   description = "Detects multiple failed user logins within 10-minute windows."
   severity = "HIGH"

  events:
   $e.metadata.event_type = "USER_LOGIN"
   $e.security_result.action = "FAIL"
   $user = $e.target.user.userid

  match:
   $user over 10m

  outcome:
   $failed_login_count = count($e.metadata.id)
   $first_fail_time = min($e.metadata.event_timestamp.seconds)

  condition:
   #e >= 5
}

בקטע outcome מתבצעות צבירות על משתני האירוע וה-placeholder: ספירת הכניסות שנכשלו, ספירת כתובות ה-IP הייחודיות וקבלת השעה שבה הכניסה נכשלה.

outcome:
   $failed_login_count = count($e.metadata.id)
   $first_fail_time = min($e.metadata.event_timestamp.seconds)

אם כוללים את משתנה התוצאה המיוחד $risk_score ומאכלסים אותו, הערך שלו (מספר שלם או מספר עשרוני) מוצג בדף Alerts and IoCs לגבי התראות שנוצרו על ידי השאילתה.

אם לא כוללים משתנה $risk_score בקטע outcome של שאילתה, אחת מהגדרות ברירת המחדל הבאות מוגדרת:

  • אם השאילתה מוגדרת ליצירת התראה, הערך של $risk_score הוא 40.

  • אם השאילתה לא מוגדרת ליצירת התראה, הערך של $risk_score הוא 15.

הערך של $risk_score מאוחסן בשדה security_result.risk_score UDM.

משתנה התוצאה risk_score

ב-Google SecOps Risk Analytics, המערכת משייכת באופן אוטומטי זיהויים והתראות לישויות שקשורות לזיהוי או להתראה. risk_score משתנה התוצאה משמש להקצאת רמת סיכון. אם לא מגדירים את הערך הזה, המערכת משתמשת בערך ברירת המחדל לזיהוי או להתראה. אפשר להגדיר ערכי ברירת מחדל בהגדרות.

כדי להבטיח עקביות בפלטפורמה, מומלץ להשתמש בטווחי הניקוד הבאים כשמקצים risk_score לזיהויים מותאמים אישית. ההתאמה הזו עוזרת ליצור סטנדרטיזציה של תעדוף ההתראות ותהליכי העבודה של התגובה.

חוּמרה טווח הציונים תיאור דוגמה
התראה – קריטית ‫90-100 פשרה פעילה עם פוטנציאל להשפיע מעבר לחשבון משתמש או נקודת קצה יחידים. נדרשת בדיקה מיידית. הפעלת Mimikatz בבקר הדומיין.
התראה – גבוהה ‫80 - 89 התפשרות פעילה על נקודת קצה או ישות יחידה. צריך לקבל בדיקה מיידית. שרת ייצור ששולח קריאה ל-C2 ידוע ועדכני.
התראות – בינוני ‫50 - 79 בעיה אפשרית באבטחה שדורשת חקירה. לא אושרה פריצה, אבל אפשר להעביר את הבעיה לטיפול ברמה גבוהה יותר. פרטי כניסה שנחשפו, ללא סימנים לשימוש לרעה.
לא מופיעה התראה – נמוך ‫20 - 49 אירוע אבטחה עם השפעה נמוכה, שכשמשלבים אותו עם אינדיקטורים או תצפיות אחרים, יכול להוביל לאירוע משמעותי יותר. בדרך כלל לא נדרשת בדיקה, אפשר לשלב עם זיהויים אחרים באמצעות כללים מורכבים כדי ליצור התראה. סריקת יציאות פנימית.
קריטריונים לבדיקה שלא מפעילים התראות ‫1 עד 19 באופן כללי, זיהויים שמבוססים על מידע נועדו ליצור מודעות למצב של איום. בדרך כלל לא נדרשת בדיקה. אפשר לשלב אותו עם זיהויים אחרים באמצעות כללים מורכבים כדי ליצור התראות. אירוע התחברות, ללא סימנים לשימוש לרעה.

מכיוון ש-risk_score הוא משתנה של תוצאה, הכללים יכולים לבטא ניואנסים בהתאם לגורמים כמו מודיעין איומי סייבר או תנאים מקבילים אחרים.

אפשר להשתמש בציוני סיכון של ישויות כדי ליצור התראות מבוססות-סיכון כמעט בזמן אמת. מידע נוסף זמין במאמר סקירה כללית של ניתוח סיכונים.

משתנה התוצאה risk_entity_to_score

בנוסף למשתנה התוצאה risk_score, אפשר לציין גם את משתנה התוצאה risk_entity_to_score. המשתנה הזה מאפשר לכם לציין במפורש אילו ישויות מזיהוי של כלל צריכות לקבל את ציון הסיכון של הזיהוי הזה.

אפשר ליצור כמה משתני risk_entity_to_score על ידי הוספת מחרוזת ייחודית למשתנה, ולהקצות את ציון הסיכון לישויות ספציפיות. לדוגמה:

$risk_entity_to_score_source_asset = $e.principal.asset.hostname
$risk_entity_to_score_targeted_user = $e.target.user.userid

משתני התוצאה האלה מקצים את risk_score שצוין בקטע outcome של הכלל לישויות $e.principal.asset.hostname ו-$e.target.user.userid.

דוגמה: כלל שמזהה כניסות לחשבונות אדמין

הכלל הזה מזהה כניסות מוצלחות לחשבונות אדמין עם הרשאות גבוהות. היא משתמשת במילת המפתח risk_entity_to_score כדי לטרגט באופן מפורש את המשתמש הספציפי שמחובר לחשבון. השימוש במשתנה הזה מבטיח שהזיהוי יתבסס על חישוב של ציון הסיכון שרלוונטי רק למשתמש הזה, ולא לישויות אחרות שמעורבות באירוע, כמו כתובת ה-IP של המקור.

פרטים על כתיבת כלל עם כמה אירועים זמינים במאמר בנושא כלל עם כמה אירועים.

rule suspicious_admin_privilege_escalation {
 // This rule matches single events. Rules can also match multiple events within
 // the same time window.

 meta:
   // Allows for storage of arbitrary key-value pairs of rule details, such as 
   // who wrote it, what it detects on, and version control.
   // The "author" and "severity" fields are special, since they are used as
   // columns on the rules dashboard. To sort based on these fields on the 
   // dashboard, add them here.
   // Severity value should be "Low", "Medium", or "High"
   author = "analyst123"
   description = "Detects suspicious login to critical admin accounts."
   severity = "HIGH"

 events:
   $e.metadata.event_type = "USER_LOGIN"
   $e.target.user.attribute.roles.name = "ADMIN"
   $e.security_result.summary = "Successful login with high-privilege access"

 outcome:
   // Multi-event rules require an aggregation function
   // For example, risk_score = max(0)
   // See https://cloud.google.com/chronicle/docs/detection/yara-l-2-0-overview#outcome_conditionals_example_rule
   $risk_score = 80
   $risk_entity_to_score = $e.target.user.userid
   $source_ip = array_distinct($e.principal.ip)

 condition:
   $e
}

דוגמה: כלל שמנטר חיבורים לרשת פנימית

הכלל הזה בודק תנועה רוחבית על ידי זיהוי חיבורים לרשת בין פלחים של רשת פנימית. הוא משתמש ב-$risk_entity_to_score prefix כדי להקצות סיכון לכמה ישויות במסגרת זיהוי אחד. ציוני הסיכון של המארח שיזם את הפעולה ($risk_entity_to_score_source_asset) ושל המשתמש שהיה היעד שלה ($risk_entity_to_score_targeted_user) מתעדכנים. מנוע הסיכון מתעד משתני תוצאה אחרים שלא משתמשים בקידומת הספציפית הזו להקשר, אבל מתעלם מהם (ציוני הסיכון שלהם נשארים זהים).

פרטים על כתיבת כלל מרובה אירועים זמינים במאמרים בנושא כלל מרובה אירועים וכלל לדוגמה עם תנאים לתוצאה.

rule lateral_movement_network_connection {
 // This rule matches single events. You can also match multiple events within
 // the same time window.

 meta:
   // Allows for storage of arbitrary key-value pairs of rule details (for 
   // example, who wrote it, what it detects on, and version control).
   // The "author" and "severity" fields are special, since they are used as
   // columns on the rules dashboard. To sort based on these fields on the 
   // dashboard, add them here. Severity value should be "Low", "Medium" or "High"
   author = "analyst123"
   description = "Detects lateral movement attempts between internal segments."
   severity = "MEDIUM"

 events:
   $e.metadata.event_type = "NETWORK_CONNECTION"
   $e.principal.asset.hostname != ""
   $e.target.user.userid != ""
   // Can also use: $e.target.ip = /10\..*/
   net.ip_in_range_cidr($e.target.ip, "10.0.0.0/8")

 outcome:
   // Multi-event rules require an aggregation function
   // for example, risk_score = max(0)
   // See https://docs.cloud.google.com/chronicle/docs/yara-l/yara-l-2-0-examples#outcome-conditionals-example-rule
   $risk_score = 50
   $risk_entity_to_score_source_asset = $e.principal.asset.hostname
   $risk_entity_to_score_targeted_user = $e.target.user.userid
   $target_ip_info = array_distinct($e.target.ip)

 condition:
   $e
}

סוגי נתונים של משתני התוצאה

לכל משתנה תוצאה יכול להיות סוג נתונים שונה, שנקבע לפי הביטוי שמשמש לחישוב שלו. סוגי נתוני התוצאות הבאים נתמכים ב-Google SecOps:

  • מספר שלם
  • צף
  • מחרוזת
  • רשימות של מספרים שלמים
  • רשימות של נקודות צפות
  • רשימות של מחרוזות

לוגיקה של משפט תנאי

אפשר להשתמש בלוגיקה מותנית כדי לחשב את ערך התוצאה. מגדירים תנאים באמצעות תבנית התחביר הבאה:

if(BOOL_CLAUSE, THEN_CLAUSE)
if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)

אפשר לקרוא ביטוי מותנה כך: 'אם BOOL_CLAUSE הוא true, אז מחזירים THEN_CLAUSE, אחרת מחזירים ELSE_CLAUSE'.

הערך של BOOL_CLAUSE חייב להיות בוליאני. ביטוי BOOL_CLAUSE דומה לביטויים שמופיעים בקטע events. לדוגמה, הוא יכול לכלול:

  • שמות שדות ב-UDM עם אופרטור השוואה:

    if($context.graph.entity.user.title = "Vendor", 100, 0)

  • משתנה placeholder שהוגדר בקטע events:

    if($severity = "HIGH", 100, 0)

  • משתנה תוצאה נוסף שהוגדר בקטע outcome:

    if($risk_score > 20, "HIGH", "LOW")

  • פונקציות שמחזירות ערך בוליאני:

    if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)

  • חיפוש ברשימת הפניות:

    if($u.principal.hostname in %my_reference_list_name, 100, 0)

  • השוואה בין צבירות:

    if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)

הסוג של הנתונים ב-THEN_CLAUSE וב-ELSE_CLAUSE חייב להיות זהה. אנחנו תומכים במספרים שלמים, במספרים עשרוניים ובמחרוזות.

אפשר להשמיט את ELSE_CLAUSE אם סוג הנתונים הוא מספר שלם או מספר עשרוני. אם משמיטים את הארגומנט, הפונקציה ELSE_CLAUSE מחזירה 0. לדוגמה:

`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`

חובה לספק את ELSE_CLAUSE אם סוג הנתונים הוא מחרוזת או אם THEN_CLAUSE הוא משתנה placeholder או משתנה תוצאה.

פעולות מתמטיות

אפשר להשתמש בפעולות מתמטיות כדי לחשב נתונים מסוג integer או float בקטעים outcomeוevents של שאילתה. ‫Google Security Operations תומך בפעולות חיבור, חיסור, כפל, חילוק ומודולו כאופרטורים ברמה העליונה בחישוב.

קטע הקוד הבא הוא דוגמה לחישוב בקטע outcome:

outcome:
  $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))

מותר לבצע פעולות מתמטיות על סוגי האופרנדים הבאים, כל עוד כל אופרנד וכל הביטוי האריתמטי מצורפים בצורה נכונה (ראו צירופים):

  • שדות מספריים של אירועים
  • משתני פלייסהולדר מספריים שמוגדרים בקטע events
  • משתני תוצאה מספריים שהוגדרו בקטע outcome
  • פונקציות שמחזירות מספרים שלמים או מספרים עשרוניים
  • צבירות שמחזירות מספרים שלמים או מספרים עשרוניים

אסור להשתמש בפעולת מודולו על מספרים ממשיים.

משתני פלייסהולדר בתוצאות

כשמחשבים משתני תוצאה, אפשר להשתמש במשתני placeholder שהוגדרו בקטע events של השאילתה. בדוגמה הזו, נניח ש-$email_sent_bytes הוגדר בקטע events (אירועים) של הכלל:

דוגמה: אירוע יחיד ללא קטע התאמה

// No match section, so this is a single-event query.

outcome:
  // Use placeholder directly as an outcome value.
  $my_outcome = $email_sent_bytes

  // Use placeholder in a conditional.
  $other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")

condition:
  $e

דוגמה: אירוע מרובה עם קטע התאמה

match:
  // This is a multi event query with a match section.
  $hostname over 5m

outcome:
  // Use placeholder directly in an aggregation function.
  $max_email_size = max($email_sent_bytes)

  // Use placeholder in a mathematical computation.
  $total_bytes_exfiltrated = sum(
    1024
    + $email_sent_bytes
    + $file_event.principal.file.size
  )

condition:
  $email_event and $file_event

משתני התוצאה בביטויי הקצאת התוצאה

אפשר להשתמש במשתני תוצאה כדי לגזור משתני תוצאה אחרים, בדומה למשתני placeholder שמוגדרים בקטע events. אפשר להפנות למשתנה של תוצאה בהקצאה של משתנה אחר של תוצאה באמצעות טוקן $ ואחריו שם המשתנה. צריך להגדיר את משתני התוצאה לפני שאפשר להפנות אליהם בטקסט של השאילתה. כשמשתמשים במשתני תוצאה בביטוי של הקצאה, אסור לצבור אותם (ראו צבירות).

בדוגמה הבאה, משתנה התוצאה $risk_score מקבל את הערך שלו ממשתנה התוצאה $event_count:

דוגמה: משתנה תוצאה שנגזר ממשתנה תוצאה אחר

match:
  // This is a multi event query with a match section.
  $hostname over 5m

outcome:
  // Aggregates all timestamp on login events in the 5 minute match window.
  $event_count = count($login.metadata.event_timestamp.seconds)

  // $event_count cannot be aggregated again.
  $risk_score = if($event_count > 5, "SEVERE", "MODERATE")

  // This is the equivalent of the 2 outcomes combined.
  $risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE")

condition:
  $e

אפשר להשתמש במשתני תוצאה בכל סוג של ביטוי בצד שמאל של הקצאת תוצאה, חוץ מהביטויים הבאים:

  • צבירות
  • Arrays.length() בקשות להפעלת פונקציות
  • עם מקשי הצירוף any או all

צבירות

שדות אירוע חוזרים הם ערכים לא סקלריים. כלומר, משתנה יחיד מצביע על כמה ערכים. לדוגמה, משתנה שדה האירוע $e.target.ip הוא שדה חוזר ויכולים להיות בו אפס, אחד או הרבה ערכים של כתובות IP. זהו ערך לא סקלרי. לעומת זאת, המשתנה של שדה האירוע $e.principal.hostname הוא לא שדה חוזר ויש לו רק ערך אחד (כלומר, ערך סקלרי).

באופן דומה, גם שדות אירועים לא חוזרים וגם שדות אירועים חוזרים שמשמשים בקטע outcome של שאילתה עם חלון התאמה הם ערכים לא סקלריים.

דוגמה: קיבוץ אירועים עם קטע התאמה ושדה לא חוזר

השאילתה הבאה מקבצת אירועים באמצעות קטע `match` ומתייחסת לשדה אירוע שלא חוזר על עצמו בקטע `outcome`:

rule OutcomeAndMatchWindow{
  ...
  match:
    $userid over 5m
  outcome:
    $hostnames = array($e.principal.hostname)
  ...
}

כל חלון של 5 דקות שבו השאילתה מופעלת עשוי להכיל אפס, אירוע אחד או הרבה אירועים. החישוב של הקטע 'תוצאה' מתבצע על כל האירועים בחלון ההתאמה. כל משתנה של שדה אירוע שאליו מתייחסים בקטע outcome יכול להצביע על אפס, על ערך אחד או על הרבה ערכים של השדה בכל אירוע בחלון ההתאמה. לדוגמה, אם חלון של 5 דקות מכיל 5 אירועים מסוג $e, $e.principal.hostname בקטע התוצאה יצוינו חמישה שמות מארחים שונים. המשתנה של שדה האירוע $e.principal.hostname מטופל כערך לא סקלרי בקטע outcome של השאילתה הזו.

משתני התוצאה תמיד צריכים להניב ערך סקלרי יחיד, ולכן כל ערך לא סקלרי שהקצאת תוצאה תלויה בו צריך לעבור צבירה כדי להניב ערך סקלרי יחיד. בקטע של תוצאה, הערכים הבאים הם לא סקלריים וחובה לצבור אותם:

  • שדות אירועים (חוזרים או לא חוזרים) כשהשאילתה משתמשת בקטע match
  • משתני placeholder של אירועים (חוזרים או לא חוזרים) כשהשאילתה משתמשת בקטע match
  • שדות אירועים חוזרים כשהשאילתה לא משתמשת בקטע match
  • מצייני מיקום חוזרים לאירועים כשהשאילתה לא משתמשת בקטע match

אפשר להשתמש בפונקציות צבירה בשדות סקלריים של אירועים, במחזיקי מקום סקלריים של אירועים ובקבועים בשאילתות שלא כוללות קטע match. עם זאת, ברוב המקרים, הצבירות האלה מחזירות את הערך העטוף, ולכן הן מיותרות. יוצא מן הכלל הוא array() aggregation, שאפשר להשתמש בו כדי להמיר באופן מפורש ערך סקלרי למערך.

משתני התוצאה מטופלים כמו צבירות: אסור לצבור אותם מחדש כשמפנים אליהם בהקצאת תוצאה אחרת.

אפשר להשתמש בפונקציות הצבירה הבאות:

פונקציית צבירה תיאור
max() הפונקציה מחזירה את הערך המקסימלי מבין כל הערכים האפשריים. פועל רק עם מספרים שלמים ומספרים עשרוניים.
min() הפונקציה מחזירה את המינימום מכל הערכים האפשריים. פועל רק עם מספרים שלמים ומספרים עשרוניים.
sum() הפונקציה מחזירה את הסכום של כל הערכים האפשריים. פועל רק עם מספרים שלמים ומספרים עשרוניים.
count_distinct() הפונקציה אוספת את כל הערכים האפשריים, ואז מחזירה את מספר הערכים האפשריים הייחודיים.
count() הפונקציה פועלת כמו count_distinct(), אבל מחזירה ספירה לא ייחודית של ערכים אפשריים.
array_distinct() הפונקציה אוספת את כל הערכים הנפרדים האפשריים, ואז מחזירה רשימה של הערכים האלה. קודם מתבצעת הסרת כפילויות כדי ליצור רשימה ייחודית, ואז מתבצעת חיתוך. בחיפוש Google, הרשימה נחתכת למקסימום של 1,000 רכיבים אקראיים. במרכזי הבקרה ובכללים, הרשימה נחתכת למקסימום של 25 רכיבים אקראיים.
array() הפונקציה פועלת כמו array_distinct(), אבל מחזירה רשימה של ערכים לא ייחודיים. בחיפוש Google, הרשימה נחתכת למקסימום של 1,000 רכיבים אקראיים. במרכזי הבקרה ובכללים, הרשימה נחתכת למקסימום של 25 רכיבים אקראיים.

הפונקציה aggregate חשובה כשכלל כולל קטע condition שמציין שצריכים להתקיים כמה אירועים, כי הפונקציה aggregate תפעל על כל האירועים שיצרו את הזיהוי.

דוגמה: תנאי לכמה אירועים

הדוגמה הבאה מציגה תנאי למספר אירועים. אם בקטע התוצאה והתנאי מופיעים:

outcome:
  $asset_id_count = count($event.principal.asset_id)
  $asset_id_distinct_count = count_distinct($event.principal.asset_id)

  $asset_id_list = array($event.principal.asset_id)
  $asset_id_distinct_list = array_distinct($event.principal.asset_id)

condition:
  #event > 1

מכיוון שבקטע `condition` נדרש יותר מ-`event` אחד לכל זיהוי, הפונקציות המצטברות יפעלו על כמה אירועים. נניח שהאירועים הבאים יצרו זיהוי אחד:

event:
  // UDM event 1
  asset_id="asset-a"

event:
  // UDM event 2
  asset_id="asset-b"

event:
  // UDM event 3
  asset_id="asset-b"

אז ערכי התוצאות יהיו:

    $asset_id_count = 3
    $asset_id_distinct_count = 2
    $asset_id_list = `["asset-a", "asset-b", "asset-b"]
    $asset_id_distinct_list = `["asset-a", "asset-b"]

מגבלות

  • בקטע outcome אי אפשר להפנות למשתנה placeholder חדש שלא הוגדר כבר בקטע events או בקטע outcome.

  • בקטע outcome אי אפשר להשתמש במשתני אירועים שלא הוגדרו בקטע events.

  • בקטע outcome אפשר להשתמש בשדה אירוע שלא נעשה בו שימוש בקטע events, בתנאי שמשתנה האירוע שאליו שייך שדה האירוע כבר הוגדר בקטע events.

  • בקטע outcome אפשר לבצע קורלציה רק בין משתני אירועים שכבר בוצעה ביניהם קורלציה בקטע events. קורלציות מתרחשות כששני שדות אירועים ממשתני אירועים שונים שווים זה לזה.

דוגמאות לקטע outcome מופיעות במאמר סקירה כללית של YARA-L 2.0.

פרטים נוספים על ביטול כפילויות של זיהויים באמצעות הקטע outcome זמינים במאמר בנושא יצירת ניתוח נתונים מבוסס-הקשר.

המאמרים הבאים

מידע נוסף

הבעיה עדיין לא נפתרה? קבלת תשובות מחברי הקהילה וממומחי Google SecOps.