שדות חוזרים

נתמך ב:

במודל הנתונים המאוחד (UDM), חלק מהשדות מסומנים כ'חוזרים', מה שמציין שהם רשימות של ערכים או סוגים אחרים של הודעות. במאמר הזה מוסבר איך להשתמש בביטויים, ב-placeholders, באינדקס של מערכים ובהודעות חוזרות בשדות חוזרים של UDM.

ביטויים בוליאניים ושדות חוזרים

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

נניח שיש לכם את האירוע הבא:

event_original {
  principal {
    // ip is a repeated field
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "host"
  }
}

ביטויים ששופרו

משתמשים במגדירי השדה any ו-all בביטויים בשדות חוזרים.

  • any – אם כל רכיב של השדה שחוזר על עצמו עומד בתנאי, האירוע כולו עומד בתנאי. לדוגמה:

    • event_original satisfies any $e.principal.ip = "192.0.2.1"
    • event_original נכשל any $e.repeated_field.field_a = "9.9.9.9"
  • all – אם כל הרכיבים של השדה החוזר עומדים בתנאי, האירוע כולו עומד בתנאי. לדוגמה:

    • event_original satisfies net.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")
    • event_original נכשל all $e.principal.ip = "192.0.2.2"

כשכותבים תנאי עם any או all, חשוב לדעת שהוספת השלילה not לתנאי לא תמיד תהיה שוות ערך לשימוש באופרטור השלילה.

לדוגמה:

  • not all $e.principal.ip = "192.168.12.16" בודקת אם לא כל כתובות ה-IP תואמות ל-192.168.12.16, כלומר השאילתה בודקת שלפחות כתובת IP אחת לא תואמת ל-192.168.12.16
  • all $e.principal.ip != "192.168.12.16" בודק אם כל כתובות ה-IP לא תואמות ‫192.168.12.16, כלומר השאילתה בודקת שאין כתובות IP שתואמות ל-192.168.12.16

מגבלות:

  • האופרטורים any ו-all תואמים רק לשדות חוזרים (לא לשדות סקלריים).
  • אי אפשר להשתמש ב-any וב-all כדי לצרף שני שדות חוזרים. לדוגמה, הערך any $e1.principal.ip = $e2.principal.ip לא תקין.
  • אין תמיכה באופרטורים any ו-all בביטוי של רשימת ההפניות.

ביטויים שלא שונו

כשמשתמשים בביטויים ללא שינוי, כל רכיב בשדה החוזר מטופל בנפרד. אם שדה חוזר של אירוע מכיל n רכיבים, השאילתה מוחלת על n עותקים של האירוע, כאשר כל עותק מכיל אחד מהרכיבים של השדה החוזר. העותקים האלה הם זמניים ולא נשמרים.

הכלל חל על העותקים הבאים:

העתקת אירוע principal.ip principal.hostname
event_copy_1 ‪"192.0.2.1" "host"
event_copy_2 ‪"192.0.2.2" "host"
event_copy_3 ‪"192.0.2.3" "host"

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

דוגמה: ביטויים שלא שונו

הכלל הבא מחזיר התאמה אחת כשהוא מופעל על מערך הנתונים של הדוגמה event_original, כי event_copy_1 עומד בכל תנאי האירועים:

rule repeated_field_1 {
  meta:
  events:
    net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/8") // Checks if IP address matches 192.x.x.x
    $e.principal.ip = "192.0.2.1"
  condition:
    $e
}

הכלל הבא לא מחזיר התאמה כשמריצים אותו על event_originalמערך הנתונים לדוגמה, כי אין עותק של האירוע ב-$e.principal.ip שמקיים את _כל_ תנאי האירוע.

rule repeated_field_2 {
  meta:
  events:
    $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.2"
  condition:
    $e
}

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

rule repeated_field_3 {
  meta:
  events:
    any $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.3"
  condition:
    $e
}

הכלל חל על העותקים הבאים:

העתקת אירוע principal.ip any $e.principal.ip
event_copy_1 ‪"192.0.2.1" ‪['192.0.2.1', '192.0.2.2', '192.0.2.3']
event_copy_2 ‪"192.0.2.2" ‪['192.0.2.1', '192.0.2.2', '192.0.2.3']
event_copy_3 ‪"192.0.2.3" ‪['192.0.2.1', '192.0.2.2', '192.0.2.3']

במקרה הזה, כל העותקים עומדים בתנאי any $e.principal.ip = "192.0.2.1", אבל רק העותק event_copy_3 עומד בתנאי $e.principal.ip = "192.0.2.3". כתוצאה מכך, האירוע כולו יתאים.

דרך נוספת להבין את סוגי הביטויים האלה היא:

  • ביטויים בשדות חוזרים שמשתמשים ב-any או ב-all פועלים על הרשימה ב-event_original.
  • ביטויים בשדות חוזרים שלא נעשה בהם שימוש ב-any או ב-all פועלים על אירועי event_copy_n בודדים.

מצייני מיקום ושדות חוזרים

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

דוגמה: פלייסהולדר של שדה חוזר

בדוגמה הבאה נוצרת התאמה אחת. ה-placeholder‏ `$ip` שווה ל-`192.0.2.1` עבור `event_copy_1`, ולכן הוא עומד בתנאים של הכלל. דוגמאות האירועים של ההתאמה מכילות רכיב יחיד, event_original.

// Generates 1 match.
rule repeated_field_placeholder1 {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1"
    $host = $e.principal.hostname

  match:
    $host over 5m

  condition:
    $e
}

בדוגמה הבאה נוצרות שלוש התאמות. ה-placeholder‏ $ip שווה לערכים שונים, לכל אחד מהעותקים השונים של event_copy_n. הקיבוץ מתבצע לפי $ip כי הוא נמצא בקטע של ההתאמה. לכן, מתקבלות שלוש התאמות, ולכל התאמה יש ערך שונה למשתנה ההתאמה $ip. לכל התאמה יש את אותה דוגמה לאירוע: רכיב יחיד, event_original.

// Generates 3 matches.
rule repeated_field_placeholder2 {
  meta:
  events:
    $ip = $e.principal.ip
    net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x

  match:
    $ip over 5m

  condition:
    $e
}

תוצאות באמצעות פלייסהולדרים שהוקצו לשדות חוזרים

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

נבחן את הכלל הבא:

rule outcome_repeated_field_placeholder {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1" or $ip = "192.0.2.2"
    $host = $e.principal.hostname

  match:
    $host over 5m

  outcome:
    $o = array_distinct($ip)

  condition:
    $e
}

יש ארבעה שלבי ביצוע לכלל הזה. השלב הראשון הוא העתקת האירועים:

העתקת אירוע $ip ‎$host $e
event_copy_1 ‪"192.0.2.1" "host" event_id
event_copy_2 ‪"192.0.2.2" "host" event_id
event_copy_3 ‪"192.0.2.3" "host" event_id

בקטע 'אירועים' יסוננו השורות שלא תואמות למסננים:

העתקת אירוע $ip ‎$host $e
event_copy_1 ‪"192.0.2.1" "host" event_id
event_copy_2 ‪"192.0.2.2" "host" event_id

התוצאה event_copy_3 סוננה כי הערך "192.0.2.3" לא עומד בדרישות של $ip = "192.0.2.1" or $ip = "192.0.2.2".

הקטע match יקובץ לפי משתני התאמה והקטע outcome יבצע צבירה בכל קבוצה:

‎$host $o $e
"host" ‪["192.0.2.1", "192.0.2.2"] event_id

הערך של $o = array_distinct($ip) מחושב באמצעות $ip מהשלב הקודם ולא מהשלב של העתקת האירועים.

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

התג $o לא מכיל את כל הרכיבים מ-$e.principal.ip כי לא כל הרכיבים עמדו בכל התנאים בקטע events. עם זאת, כל הרכיבים של e.principal.ip יופיעו בדוגמת האירוע כי בדוגמת האירוע נעשה שימוש ב-event_original.

הוספה לאינדקס של מערך

אפשר לבצע אינדקס של מערכים בשדות חוזרים. כדי לגשת לרכיב השדה החוזר ה-n-י, משתמשים בתחביר של רשימה רגילה (הרכיבים ממוספרים מ-0). אם המיקום של הרכיב חורג מהגבולות, הפונקציה מחזירה את ערך ברירת המחדל.

  • $e.principal.ip[0] = "192.168.12.16"
  • $e.principal.ip[999] = "" אם יש פחות מ-1,000 רכיבים, הערך שמוחזר הוא true.

מגבלות:

  • האינדקס חייב להיות מספר שלם לא שלילי. לדוגמה, הערך $e.principal.ip[-1] לא תקין.
  • ערכים מסוג int (לדוגמה, placeholder שמוגדר כ-int) לא נספרים.
  • אי אפשר לשלב אינדקסים של מערכים עם any או all. לדוגמה, הערך any $e.intermediary.ip[0] לא תקין.
  • אי אפשר לשלב בין אינדקסים של מערכים לבין תחביר של מפות. לדוגמה, הערך $e.additional.fields[0]["key"] לא תקין.
  • אם נתיב השדה מכיל כמה שדות חוזרים, צריך להשתמש באינדקס של מערך בכל השדות החוזרים. לדוגמה, $e.intermediary.ip[0] הוא לא נתיב תקין כי intermediary ו-ip הם שדות חוזרים, אבל יש אינדקס רק ל-ip.

הודעות חוזרות

כששדה message חוזר על עצמו, ההשפעה הלא מכוונת היא הפחתת הסיכוי להתאמה. הדוגמאות הבאות ממחישות את זה.

נניח שיש לכם את האירוע הבא:

event_repeated_message {
  // about is a repeated message field.
  about {
    // ip is a repeated string field.
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "alice"
  }
  about {
    hostname: "bob"
  }
}

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

rule repeated_message_1 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about.hostname = "bob"
  condition:
    $e
}

הכלל חל על העותקים הבאים:

העתקת אירוע about.ip about.hostname
event_copy_1 ‪"192.0.2.1" "alice"
event_copy_2 ‪"192.0.2.2" "alice"
event_copy_3 ‪"192.0.2.3" "alice"
event_copy_4 "" "bob"

האירוע לא תואם לכלל כי אין עותק של האירוע שמקיים את כל הביטויים.

הודעות חוזרות ואינדקס של מערכים

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

rule repeated_message_2 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about[1].hostname = "bob"
  condition:
    $e
}

הכלל חל על העותקים הבאים:

העתקת אירוע about.ip about[1].hostname
event_copy_1 ‪"192.0.2.1" "bob"
event_copy_2 ‪"192.0.2.2" "bob"
event_copy_3 ‪"192.0.2.3" "bob"
event_copy_4 "" "bob"

מכיוון שהערך event_copy_1 עומד בכל הביטויים ב-repeated_message_2, האירוע תואם לכלל.

זה עלול להוביל להתנהגות לא צפויה כי לכלל repeated_message_1 לא היה אינדקס של מערך והוא לא הפיק התאמות, בעוד שלכלל repeated_message_2 היה אינדקס של מערך והוא הפיק התאמה.

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