שדות חוזרים
במודל הנתונים המאוחד (UDM), חלק מהשדות מסומנים כ'חוזרים', מה שמציין שהם רשימות של ערכים או סוגים אחרים של הודעות. במאמר הזה מוסבר איך להשתמש בביטויים, בפלייסהולדרים, בהוספה לאינדקס של מערכים ובהודעות חוזרות בשדות 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_originalsatisfiesany $e.principal.ip = "192.0.2.1"-
event_originalנכשלany $e.repeated_field.field_a = "9.9.9.9"
all– אם כל הרכיבים של השדה החוזר עומדים בתנאי, האירוע כולו עומד בתנאי. לדוגמה:-
event_originalעומד בתנאי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בודדים.
פלייסהולדרים ושדות חוזרים
שדות חוזרים פועלים עם הקצאות של placeholder. בדומה לביטויים שלא עברו שינוי בשדות חוזרים, נוצר עותק של האירוע לכל רכיב. באותו דוגמה של event_copy, הפלייסהולדר מקבל את הערך של השדה החוזר של event_copy_n, לכל אחת מהעותקים של האירוע, כאשר n הוא מספר העותק של האירוע. אם משתמשים ב-placeholder בקטע של ההתאמה, יכולות להיות כמה התאמות.
דוגמה: פלייסהולדר של שדה חוזר
בדוגמה הבאה נוצרת התאמה אחת. ה-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
}
בדוגמה הבאה נוצרות שלוש התאמות. הפלייסהולדר $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
}
תוצאות באמצעות פלייסהולדרים שהוקצו לשדות חוזרים
מצייני מיקום מוקצים לכל רכיב בכל שדה חוזר, ולא לרשימה כולה. כשמשתמשים בהם בקטע 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 כי לא כל הרכיבים עמדו בכל התנאים בקטע האירועים. עם זאת, כל הרכיבים של 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.