יצירת כללי זיהוי מורכבים
במאמר הזה מוסבר איך ליצור כלל מורכב בפלטפורמת Google Security Operations. התהליך כולל חיבור של כמה כללי YARA-L 2.0 כדי לזהות דפוסי תקיפה מורכבים. זיהויים מורכבים בנויים ככללים מרובי-אירועים, והם שומרים על אותה תחביר בסיסי כמו כללים רגילים של אירוע יחיד. מידע נוסף זמין במאמר סקירה כללית על זיהויים מורכבים.
הסבר על מבנה הכללים
כללי זיהוי מורכבים הם תמיד כללים מרובי-אירועים, והם פועלים לפי אותה מבנה ותחביר כמו כלל חד-אירועי.
כלל מורכב כולל את הרכיבים הבאים:
הקטע
events: מגדיר את הקלט, כלומר את הזיהויים או האירועים הספציפיים שהכלל מנתח.הקטע
match: מציין איך צריך לחבר את נתוני הקלט בחלון זמן מוגדר.קטע
condition: מכיל את הלוגיקה הסופית שקובעת אם האירועים שצורפו עומדים בקריטריונים להפעלת התראה.
הגדרת הקלט בקטע events
השלב הראשון ביצירת כלל מורכב לזיהוי הוא הגדרת הקלט של הכלל בקטע events. הקלט לכללים מורכבים מגיע מאוספים, שבהם מאוחסנים הזיהויים שנוצרו על ידי שאילתות אחרות.
ב-Google SecOps יש שתי שיטות לגישה לנתונים מקולקציות.
הפניה לתוכן לזיהוי באמצעות משתנים או תוויות מטא
כדי לגשת לנתונים מזיהוי בלי להפנות לאירועי ה-UDM המקוריים,
אפשר להשתמש במשתני outcome, במשתני match או בתוויות meta. מומלץ להשתמש בגישה הזו כי היא גמישה יותר ומתאימה יותר לסוגים שונים של כללים.
לדוגמה, כמה כללים יכולים לאחסן מחרוזת (כמו כתובת URL, שם קובץ או מפתח רישום) במשתנה outcome משותף אם אתם מחפשים את המחרוזת הזו בהקשרים שונים. כדי לגשת למחרוזת הזו מכלל מורכב, מתחילים עם detection ומאתרים את המידע הרלוונטי באמצעות אלמנטים ממשאב האוסף.
דוגמה: נניח שכלל זיהוי מפיק את המידע הבא:
משתנה התוצאה:
dest_domain = "cymbal.com"שדה UDM:
target.hostname = "cymbal.com"
בכלל המורכב, אפשר לגשת לנתונים האלה באמצעות הנתיבים הבאים:
detection.detection.outcomes["dest_domain"]כדי לגשת למשתנה התוצאהdest_domain.detection.collection_elements.references.event.target.hostnameכדי לגשת לשדהtarget.hostnameUDM.
detection.time_window.start_time.secondsכדי לגשת לחותמת הזמן של תחילת הזיהוי.
Collection API ו-SecurityResult API מאפשרים גישה לשני סוגי הנתונים:
- מטא-נתונים של זיהוי וערכי תוצאות (
detection.detection) - אירועי UDM בסיסיים מכללים שמפנים אליהם (
collection_elements)
זיהוי תוכן של הפניה באמצעות מזהה או שם של כלל
אפשר להפנות לכלל לפי השם או המזהה שלו. אנחנו ממליצים על הגישה הזו אם לוגיקת הזיהוי שלכם תלויה בכללים ספציפיים ואתם רוצים לצמצם את הנתונים שמנותחים רק לתוצאות של הכללים האלה. הפניה לכללים רלוונטיים לפי שם או מזהה משפרת את הביצועים ומונעת פסק זמן, כי היא מצמצמת את כמות הנתונים שמנותחים. לדוגמה, אפשר לשלוח שאילתה ישירות לשדות כמו target.url או principal.ip מזיהוי קודם ידוע.
הפניה לכלל באמצעות מזהה הכלל (מומלץ): משתמשים בשדה
detection.detection.rule_idכדי להפנות לכלל באמצעות המזהה שלו. אפשר למצוא את מזהה הכלל בכתובת ה-URL של הכלל ב-Google SecOps. לכללים שנוצרו על ידי משתמשים יש מזהים בפורמטru_UUID, ולגלאים מוכנים מראש יש מזהים בפורמטur_UUID. לדוגמה:detection.detection.rule_id = "ru_e0d3f371-6832-4d20-b0ad-1f4e234acb2b"הפניה לכלל לפי שם הכלל: משתמשים בשדה
detection.detection.rule_nameכדי להפנות לכלל לפי שם. אפשר לציין את השם המדויק של הכלל או להשתמש בביטוי רגולרי כדי להתאים אותו. לדוגמה:detection.detection.rule_name = "My Rule Name"detection.detection.rule_name = "/PartOfName/"
איחוד מקורות קלט בקטע match
כדי לקשר בין זיהויים, אירועים או ישויות קשורים בכלל מורכב, צריך להגדיר את הקטע match באמצעות משתנים שהוגדרו בקטע events. המשתנים האלה יכולים לכלול תוויות של כללים, משתני תוצאה, משתני התאמה, שדות זיהוי או רכיבי אוסף.
מידע על התחביר מופיע במאמר בנושא תחביר של קטע התאמה.
כללים מורכבים: חלונות זמן וחלונות קפיצה
כללים מורכבים מתאימים בין זיהויים ואירועים לבין מרווח זמן, ולא לנקודת זמן בודדת. הם תואמים לחלון זמן מורכב של קפיצה אם חלון הזמן של זיהוי הקלט חופף לחלון הזמן של הקפיצה (לדוגמה, הפעילות הייתה פעילה במהלך בלוק הזמן הזה).
זיהוי יחיד יכול להפעיל כמה התראות אם הזיהוי מתפרס על הגבול בין חלונות סמוכים של קפיצות (בגלל עיכובים בצינור, ההתאמות ההיסטוריות האלה מופיעות מאוחר יותר). ספציפית, חלון הזמן של כלל מורכב מפעיל התאמה אם חלון הזמן של זיהוי הקלט (WindowStart עד WindowEnd) חופף לחלון הזמן של הכלל.
לדוגמה:
- חלונות הזמן של כלל מורכב הם של 60 דקות: חלון 1 (18:58 עד 19:58) וחלון 2 (19:58 עד 20:58).
- חלון הזמן של זיהוי תוכן שנוצר במעלה הזרם הוא 19:57:54 - 20:56:54 (משך 59 דקות).
- חלון ההפקה התחיל בשעה 19:57:54 (6 שניות לפני שהקפיצה הראשונה הסתיימה) והסתיים בשעה 20:56:54 (במהלך הקפיצה השנייה), ולכן יש חפיפה בין חלון ההפקה לבין שני חלונות הקפיצה.
- הפעולה הזו מפעילה שני זיהויים מורכבים (אחד עבור Hop 1 ואחד עבור Hop 2), ועוזרת למנוע תוצאות שליליות שגויות. אם כלל היצרן לא תאם לחפיפה, לא תתבצע בדיקה של חפיפה חלקית עבור קפיצה 1 או קפיצה 2, ולא תהיה אפשרות לראות את הקשר בין הזיהוי לבין אירועים אחרים.
מידע נוסף ודוגמאות לאופן שבו מציינים חלונות של קפיצות זמינים במאמר בנושא חלונות של קפיצות.
הגדרת הקטע condition
מגדירים את הקטע condition כדי להעריך את התוצאות של הקטע match.
אם התנאי הוא true, נוצרת התראה. מידע על התחביר מופיע במאמר תחביר של קטע התנאים.
החלת טכניקות מתקדמות על כללים מורכבים
בקטע הזה מוסבר איך להשתמש בטכניקות מתקדמות כשיוצרים כללים מורכבים.
שילוב של אירועים וזיהויים
כללים מורכבים יכולים לשלב כמה מקורות נתונים, כולל אירועים של UDM, נתונים של גרף ישויות ושדות זיהוי. יש לפעול בהתאם להנחיות הבאות:
שימוש במשתנים נפרדים לכל מקור: מקצים משתני אירוע ייחודיים לכל מקור נתונים (לדוגמה,
$eלאירועים,$dלזיהויים), כאשר מקור הנתונים כולל אירועים, ישויות וזיהויים.צירוף מקורות על סמך הקשר משותף: אפשר לקשר מקורות נתונים באמצעות ערכים משותפים, כמו מזהי משתמשים, כתובות IP או שמות דומיין בתנאים של הכלל.
הגדרת חלון התאמה: תמיד צריך לכלול פסקה
matchעם חלון זמן שלא עולה על 48 שעות.
דוגמה: שילוב של אירועים וזיהויים
rule CheckCuratedDetection_with_EDR_and_EG {
meta:
author = "noone@cymbal.com"
events:
$d.detection.detection.rule_name = /SCC: Custom Modules: Configurable Bad Domain/
$d.detection.collection_elements.references.event.network.dns.questions.name = $domain
$d.detection.collection_elements.references.event.principal.asset.hostname = $hostname
$e.metadata.log_type = "LIMACHARLIE_EDR"
$e.metadata.product_event_type = "NETWORK_CONNECTIONS"
$domain = re.capture($e.principal.process.command_line, "\\s([a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+)$")
$hostname = re.capture($e.principal.hostname, "([^.]*)")
$prevalence.graph.metadata.entity_type = "DOMAIN_NAME"
$prevalence.graph.metadata.source_type = "DERIVED_CONTEXT"
$prevalence.graph.entity.hostname = $domain
$prevalence.graph.entity.domain.prevalence.day_count = 10
$prevalence.graph.entity.domain.prevalence.rolling_max <= 5
$prevalence.graph.entity.domain.prevalence.rolling_max > 0
match:
$hostname over 1h
outcome:
$risk_score = 80
$CL_target = array($domain)
condition:
$e and $d and $prevalence
}
יצירת זיהויים מורכבים רציפים
זיהויים מורכבים רציפים מזהים דפוסים של אירועים קשורים שבהם רצף הזיהויים חשוב, כמו זיהוי של ניסיון התחברות בכוח, ואחריו התחברות מוצלחת. התבניות האלה יכולות לשלב כמה זיהויים בסיסיים, אירועי UDM גולמיים או את שניהם.
כדי ליצור זיהוי מורכב רציף, צריך לאכוף את הסדר הזה בתוך הכלל. כדי לאכוף את הרצף הצפוי, אפשר להשתמש באחת מהשיטות הבאות:
חלונות נעים: הגדרת רצף הזיהויים באמצעות חלונות נעים בתנאי
match.השוואות של חותמות זמן: השוואה בין חותמות הזמן של זיהויים בתוך הלוגיקה של הכלל כדי לוודא שהם מתרחשים בסדר שנבחר.
דוגמה: זיהויים מורכבים רציפים
events:
$d1.detection.detection.rule_name = "fileEvent_rule"
$userid = $d1.detection.detection.outcomes["user"]
$hostname = $d1.detection.detection.outcomes["hostname"]
$d2.detection.detection.rule_name = "processExecution_rule"
$userid = $d2.detection.detection.outcomes["user"]
$hostname = $d2.detection.detection.outcomes["hostname"]
$d3.detection.detection.rule_name = "networkEvent_rule"
$userid = $d3.detection.detection.outcomes["user"]
$hostname = $d3.detection.detection.outcomes["hostname"]
$d3.detection.collection_elements.references.event.metadata.event_timestamp.seconds > $d2.detection.collection_elements.references.event.metadata.event_timestamp.seconds
match:
$userid over 24h after $d1
הבעיה עדיין לא נפתרה? קבלת תשובות מחברי הקהילה וממומחי Google SecOps.