החלת לוגיקה של חלונות YARA-L 2.0

נתמך ב:

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

לפני שמתחילים

מוודאים שיש לחשבון שלכם אחד מהתפקידים הבאים כדי ליצור ולשנות שאילתות YARA-L:

  • אדמין של מנוע הזיהוי (roles/chronicle.detectionEngineAdmin)
  • עריכה ב-SecOps (roles/chronicle.editor)

סוגי החלונות הנתמכים

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

סוג חלון הזמן שנתמך תחביר תיאור תרחיש שימוש נפוץ
Hop $key over <duration> יוצרת מרווחי זמן קבועים וחופפים. המערכת מגדירה את החפיפה וההתאמה כדי לתעד אירועים שקרו קרוב לגבולות. קורלציה כללית של כמה אירועים, בלי קשר לשעות ההתחלה המדויקות.
התעמלות קרקע $key by <duration> פילוח הנתונים לבלוקים רציפים בגודל קבוע שלא חופפים זה לזה. ההערכה מתבצעת בלי קשר למועד קבלת האירוע. כימות הפעילות במשבצות זמן קבועות (לדוגמה, $user by 30m) או זיהוי היעדר אירועים.
הזזה $key over <duration> [before|after] $pivot החלון מעוגן לאירוע "pivot" ספציפי. כדי להפעיל חיפוש אחורה או קדימה, צריך שיהיה ציר. רצף קפדני שבו סדר האירועים הוא קריטי (לדוגמה, File Download after Login).

הסבר על הלוגיקה של window_start ושל window_end

‫Google Security Operations מספקת שתי מילות מפתח אוניברסליות שמורות שמתורגמות ישירות לחותמות זמן של GoogleSQL לשימוש בשאילתות. מילות המפתח האלה מאפשרות לכם לגשת לגבולות של משבצות הזמן:

  • ‫window_start: הגבול ההתחלתי של קטגוריית הזמן.
  • ‫window_end: הגבול הסוגר של משבצת הזמן.

מגבלות שימוש

  • דרישת התאמה: כדי להשתמש במילות המפתח האלה, צריך להגדיר חלון (by או over) בקטע match.
  • הגבלת קטע: אפשר להשתמש במילות המפתח האלה ב-condition, ב-order או ב-outcome. הם לא תקינים בקטע events.
  • מרחב שמות: אל תשתמשו בשמות האלה כשמות של משתנים מותאמים אישית (לדוגמה, $window_start).

קביעת סוג החלון והתחביר

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

תרחיש טווח הזמן המומלץ מילות מפתח מומלצות יתרון מרכזי
זיהויים בתדירות גבוהה (לדוגמה, מתקפות Brute Force) חלון הזזה (over) window_start, window_end ההתראה מופעלת באופן מיידי כשמגיעים לסף בתקופה האחרונה.
היעדרות/אי-קיום (לדוגמה, פעימות לב חסרות) חלון עוקב (by) window_start, window_end הפונקציה מעריכה בלוקים קבועים של זמן גם אם לא מתרחשים אירועים, וכך מונעת שגיאות מסוג Variable Not Bounded.
דיווח כרונולוגי החלקה או נפילה order: window_start asc הפלט של ההתראות עובר סטנדרטיזציה כדי להקל על ניתוח ציר הזמן בממשק המשתמש של Chronicle.
סינון לפי זמן החלקה או נפילה condition: window_start > "2026-01-01 00:00:00Z" הגבלת הערכת הכללים לתאריכים ספציפיים באמצעות אילוץ חותמת זמן של GoogleSQL.

השוואה בין סוגים של חותמות זמן ואזורי זמן

ב-YARA-L יש תמיכה בהשוואה ישירה בין window_start לבין window_end למחרוזות בפורמט חותמת זמן של GoogleSQL. כך אפשר לבצע סינון מדויק בלי המרת טיפוסים ידנית.

הערה: תמיד צריך לציין את שעון UTC באמצעות הסיומת Z (לדוגמה, "2026-03-17T17:35:00Z") כדי להתאים לחותמות הזמן של אירועים ב-UDM.

שימוש במסננים של חותמות זמן לביצועים. אם אתם רק רוצים לוודא שאירוע אחד קרה אחרי אירוע אחר, השוואה של חותמות זמן בקטע condition היא לרוב יעילה יותר: $e1.metadata.event_timestamp.seconds < $e2.metadata.event_timestamp.seconds.

מידע נוסף על התחביר של קטע match ועל התחביר של קטע condition

דוגמאות: window_end ו-window_start

  • window_end < "2026-01-01T12:30:00Z" (תאריך, שעה וסיומת UTC)
  • ‫window_start != "2026-01-01 15:00:00+00" (עם קיזוז משעון UTC)

אם ההשוואה נכשלת, צריך לוודא שהמחרוזת שלכם תואמת לפורמט הקנוני של חותמת הזמן ב-GoogleSQL.

העברה בין חלונות

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

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

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

מידע נוסף על התחביר של קטע match

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

דוגמה: חלונות קפיצה חופפים לצורך קורלציה רציפה

בדוגמה הבאה מוצגת שאילתה שמופעלת על טווח תאריכים [1:00, 2:00], עם קטע match $user over 30m. קבוצה אפשרית של חלונות קצובים חופפים שהמערכת יוצרת היא [1:00, 1:30], [1:03, 1:33] ו-[1:06, 1:36].

כלל

rule hop_window_brute_force_example {
meta:
  description = "Detects multiple failed logins within a shifting 30-minute window."
  severity = "Medium"

events:
  $login.metadata.event_type = "USER_LOGIN"
  $login.extensions.auth.auth_status = "FAILURE"
  $login.principal.user.userid = $user

match:
  // This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
  $user over 30m

condition:
  // This will trigger if 10 or more failures fall into any single 30m hop
  #login >= 10
}
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user

match:
  // This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
  $user over 30m
  ```

מרכז שליטה

metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user

match:
  // This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
  $user over 30m

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

בדוגמה הבאה מתועדים אירועים שמתרחשים באותו פרק זמן כללי:

כלל

rule hop_window_example {
meta:
  description = "Detect a user with a failed login followed by a success within 30m"

events:
  // Event 1: Capture failed login attempts
  $fail.metadata.event_type = "USER_LOGIN"
  $fail.security_result.action = "FAIL"
  $fail.principal.user.userid = $user

  // Event 2: Capture successful login attempts
  $success.metadata.event_type = "USER_LOGIN"
  $success.security_result.action = "ALLOW"
  $success.principal.user.userid = $user

match:
  // Correlate events for the SAME $user within a rolling 30-minute window.
  $user over 30m

condition:
  // Ensure both a failed ($fail) and a successful ($success) login event occurred for the same user within the 30m window.
  $fail and $success
}

חיפוש

// Event 1: Capture failed login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user // Assign user ID to a placeholder

// Event 2: Capture successful login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "ALLOW"
principal.user.userid = $user // Link to the same user placeholder

match:
  // Correlate events for the SAME $user within a rolling 30-minute window.
  $user over 30m

מרכז שליטה

// Event 1: Capture failed login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user // Assign user ID to a placeholder

// Event 2: Capture successful login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "ALLOW"
principal.user.userid = $user // Link to the same user placeholder

match:
  // Correlate events for the SAME $user within a rolling 30-minute window.
  $user over 30m

דוגמה: השוואה של חלונות קפיצה

כדי לזהות ניסיון של מתקפת כוח ברוטלי, חלון 10m מקבץ את כל הכשלים של USER_LOGIN. לאחר מכן, התנאי מעריך אם הספירה (#e) בתוך משך הזמן הספציפי של 10 דקות חורגת מהסף שהגדרתם.

כלל

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

condition:
  #e >= 5
}

חיפוש

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

match:
  $user over 10m

מרכז שליטה

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

match:
  $user over 10m

חלונות עוקבים (tumbling windows)

הערה: התכונה הזו לא זמינה לכל הלקוחות בכל האזורים.

חלון עוקב (tumbling window) מחלק את הנתונים למרווחי זמן קבועים, לא חופפים ורציפים. חותמת הזמן של כל אירוע נכללת בחלון אחד בלבד. אין חפיפה בין חלונות עוקבים. לעומת זאת, חלון קפיצה או חלון הזזה יכולים לכלול מרווחי זמן חופפים.

כדי להטמיע חלון עוקב (tumbling window), משתמשים באופרטור by בקטע match. חלונות עוקבים (tumbling window) מחלקים את הזמן לבלוקים רציפים שמופיעים אחד אחרי השני, למשל:

  • ‫by 1h: יוצר חלונות לכל שעה (לדוגמה, [00:00:00-00:59:59], ‏ [01:00:00-01:59:59]).
  • ‫by 10m: יוצר חלונות לכל מרווח של 10 דקות (לדוגמה, [00:00:00-00:09:59], [00:10:00-00:19:59]).

תרחישים נפוצים לדוגמה

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

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

התנהגות של ביטול כפילויות

מאפיין מרכזי של חלונות מתגלגלים הוא האופן שבו המנוע מטפל בזיהויים בכל חלון עבור אותו סט של משתני התאמה:

  • זיהוי אחד לכל חלון: עבור קבוצה נתונה של ערכים של משתני ההתאמה (לדוגמה, $userid ספציפי), המנוע יוצר לכל היותר זיהוי אחד לכל חלון עוקב (tumbling window).
  • האירוע הראשון שמתקבל: האירועים הראשונים שמתקבלים ועומדים בתנאי הכלל של קבוצת משתני ההתאמה בחלון ספציפי מפעילים את הזיהוי.
  • ביטול כפילויות: אירועים עוקבים שתואמים לקריטריונים באותו מופע של חלון לא ייצרו זיהויים נוספים.

תחביר

התחביר בקטע match הוא: match: $variable by <duration>

  • ‫$variable הוא משתנה הפלייסהולדר שמתבצעת התאמה שלו.
  • ‫duration הוא מספר שאחריו יחידת זמן: m (דקה), h (שעה), d (יום).
  • צריך לציין משך זמן של דקה אחת לפחות ו-72 שעות או שלושה ימים לכל היותר.

דוגמה: קיבוץ לפי מרווח קבוע

קבוצת הכללים הבאה מקבצת התחברויות לפי $userid בחלונות של שעה אחת שלא חופפים.

כלל

rule TumblingWindowExample {
meta:
  description = "Example using a 1-hour tumbling window"

events:
  $e.metadata.event_type = "USER_LOGIN"
  $e.principal.user.userid = $userid

match:
  $userid by 1h

condition:
  $e
}

חיפוש

metadata.event_type = "USER_LOGIN"
principal.user.userid = $userid

match:
  $userid by 1h

מרכז שליטה

metadata.event_type = "USER_LOGIN"
principal.user.userid = $userid

match:
  $userid by 1h

דוגמה: התנהגות של זיהוי (משתמש = 'Alex')

  • אירוע 1: אלכס מתחבר בשעה 00:30. התאריך הזה נכלל בחלון של [00:00:00-00:59:59]. המנוע יוצר זיהוי של אלכס בחלון הזה.
  • אירוע 2: משתמש אחר, Taylor, מתחבר בשעה 00:45. גם המקרה הזה נכלל בקטגוריה [00:00:00-00:59:59], אבל בגלל ש-$userid שונה, המנוע יוצר זיהוי נפרד לטיילור.
  • אירוע 3: אלכס מתחבר שוב בשעה 00:40. זה עדיין בטווח של [00:00:00-00:59:59]. מכיוון שכבר קיים זיהוי של אלכס, האירוע הזה עובר ביטול כפילויות. לא נוצר זיהוי חדש.
  • אירוע 4: אלכס מתחבר בשעה 01:20. התאריך הזה נכלל בחלון הבא, [01:00:00-01:59:59]. המנוע יוצר זיהוי חדש לאלכס.

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

הגדרת חלונות מתגלגלים לזיהוי היעדרות

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

  1. מזהים את יעד הזיהוי. קובעים אם אתם מחפשים תדירות גבוהה או חוסר פעילות.
  2. בוחרים את windowמילת המפתח. משתמשים ב-over כדי לציין תדירות וב-by כדי לציין היעדר.
  3. הגדרת גבולות לחלון ההפניה. משתמשים במילות המפתח window_start ו-window_end כדי להפנות לגבולות ספציפיים של קטגוריית הזמן.

הקשר: משתמשים ב-outcome: $ext_window_end = window_end כדי לכלול במטא-נתונים של ההתראה את שעת הסיום המדויקת של פעימת הלב שהוחמצה.

דוגמה: זיהוי של אות חיים חסר באמצעות מטא-נתונים

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

כלל

rule missing_heartbeat_detection {
meta:
  description = "Alert when a system fails to check in within a 24h block"

events:
  $e.metadata.event_type = "STATUS_UPDATE"
  $host = $e.principal.hostname

match:
  $host by 24h  // Tumbling window lets you detect zero counts

outcome:
  $event_count = count($e.metadata.id)
  $missing_window_start = window_start
  $missing_window_end = window_end

condition:
  $event_count = 0 and window_start > "2026-01-01T12:30:00Z"
}

חיפוש

metadata.event_type = "STATUS_UPDATE"
$host = principal.hostname

match:
  $host by 24h  // Tumbling window lets you detect zero counts

outcome:
  $event_count = count(metadata.id)
  $missing_window_start = window_start
  $missing_window_end = window_end

מרכז שליטה

metadata.event_type = "STATUS_UPDATE"
$host = principal.hostname

match:
  $host by 24h  // Tumbling window lets you detect zero counts

outcome:
  $event_count = count(metadata.id)
  $missing_window_start = window_start
  $missing_window_end = window_end

חלונות הזזה

חלון הזזה מעוגן לאירוע ציר ספציפי ומסתכל קדימה (after) או אחורה (before).

תרחישים נפוצים לדוגמה

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

  • רצף קפדני: זיהוי של שרשרת התקפות (לדוגמה, e1 מתרחש עד שתי דקות אחרי e2).
  • תזמון יחסי: חיפוש אירוע שמתרחש בטווח זמן מסוים מהפעלת טריגר (לדוגמה, Network Connection תוך 30 שניות מProcess Start).
  • זיהוי היעדרות: זיהוי מצב שבו אירוע נדרש מסוג 'ניקוי' או 'דופק' לא מתרחש אחרי אירוע התחלה.

תחביר

match: <grouping_keys> over <duration> [before|after] <$pivot_event>

רכיב תיאור דוגמה
מפתחות קיבוץ שדות נפוצים שמשמשים לקישור בין אירועים. $host, $user
משך הזמן ההפרש בין הזמן של האירוע לבין הזמן של אירוע הציר. 5m, 1h, 30s
כיוון האם החלון מתרחב קדימה או אחורה. after, before
אירוע מרכזי משתנה האירוע שקובע את נקודת ההתחלה של החלון. $proc, $alert

דוגמאות לחלונות זמן נעים תקינים:

  • $var1, $var2 over 5m after $e1
  • $user over 1h before $e2
  • $host, $ip over 1h before $e2

דרישות ומגבלות

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

דוגמה: קורלציה צופה פני עתיד (after)

כלל

rule sliding_window_after_example {
meta:
  description = "Detect a network connection occurring within 1 minute after a suspicious process launch."
  severity = "High"

events:
  $proc.metadata.event_type = "PROCESS_LAUNCH"
  $proc.principal.hostname = $host

  $net.metadata.event_type = "NETWORK_HTTP"
  $net.principal.hostname = $host

match:
  // $proc is the pivot; the 1-minute window starts at the $proc timestamp
  $host over 1m after $proc

condition:
  $proc and $net
}

חיפוש

אין תמיכה ב-after בחיפוש Google.

מרכז שליטה

אין תמיכה ב-after במרכזי בקרה.

דוגמה: קורלציה רטרוספקטיבית (before)

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

כלל

rule sliding_window_before_example {
meta:
  description = "Identify file modifications occurring in the 5 minutes before a ransomware alert."
  severity = "Critical"

events:
  $file.metadata.event_type = "FILE_MODIFICATION"
  $file.principal.hostname = $host

  $alert.metadata.event_type = "ANTIVIRUS_DETECTION"
  $alert.metadata.product_name = "Premium_AV"
  $alert.principal.hostname = $host

match:
  // $alert is the pivot; the 5-minute window ends at the $alert timestamp
  $host over 5m before $alert

condition:
  $file and $alert
}

חיפוש

אין תמיכה ב-before בחיפוש.

מרכז שליטה

אין תמיכה ב-before במרכזי בקרה.

פתרון בעיות

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

זמן אחזור ומגבלות

  • כללים שמשתמשים בחלונות עוקבים (tumbling window) (by) מופעלים רק בסוף בלוק הזמן הקבוע. לדוגמה, כלל עם match: $user by 24h יוערך רק אחרי שחלון 24 השעות יסתיים.

  • השהיית התראות: כללים שמשתמשים ב-by (מתגלגל) מופעלים רק אחרי שחלף בלוק הזמן הקבוע. כלל של by 24h לא ישלח התראה באמצע החלון.

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

תיקון שגיאות

קוד שגיאה תיאור תיקון
המשתנה לא מוגבל הכלל משתמש בover (חלון הזזה) עם תנאי $count = 0. משנים את מילת המפתח של חלון הזמן ל-by (חלון זמן מתגלגל). חלונות נעים דורשים אירוע שישמש כנקודת עיגון לחלון, בעוד שחלונות מתגלגלים לא דורשים זאת.
חוסר התאמה בכותרת של ממשק המשתמש בממשק המשתמש, המשתמש רואה TIME_BUCKET במקום window_start. לא נדרש תיקון. הלוגיקה של הסינון וההזמנה עדיין פועלת בצורה תקינה באמצעות מילות המפתח.
מזהה לא מוכר: window_start מילת המפתח נמצאת בשימוש, אבל לא הוגדר חלון ב-match. מוסיפים הצהרת חלון לקטע match (לדוגמה, $hostname by 1h).
שימוש לא תקין ב-window_start באירועים מילת המפתח מוזכרת בקטע events. מעבירים את הלוגיקה לקטע condition או outcome. גבולות החלון מחושבים רק אחרי שקבוצת האירועים נמצאת בשלב ההתאמה.

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

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