בעיות מוכרות ב-YARA-L 2.0

נתמך ב:

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

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

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

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

התפקידים שצריך ב-IAM

  • ‫roles/chronicle.viewer (צפייה ב-Security Operations): כדי לראות כללים קיימים ומטא-נתונים של זיהויים.
  • ‫roles/chronicle.editor (עריכה ב-Security Operations): כדי לשנות את הלוגיקה של הכלל ולשמור את השינויים.

ההרשאות הנדרשות

  • ‫chronicle.rules.runTest: נדרשת כדי להפעיל את התכונה הרצת בדיקה על נתונים היסטוריים.

  • ‫chronicle.detections.get: כדי לבדוק את הפלט של אירועים שלא עברו ביטול של בתים מקוננים בלוח הבקרה של הזיהוי.

מונחים חשובים

  • ‫UDM (מודל נתונים מאוחד): הסכימה המנורמלת שמשמשת ליצירת מבנה לכל נתוני הטלמטריה של האבטחה שנקלטו בפלטפורמה.
  • ביטול ההתאמה: הרחבה ברמת המנוע של אירוע UDM יחיד שמכיל שדה חוזר (מערך) לכמה שורות. כל שורה מייצגת רכיב ייחודי מהמערך, מה שעלול להוביל להכפלת שורות במהלך הערכת הכללים.
  • ‫T₀ (הרצה ראשונית): ההפעלה הראשונה של כלל על נתוני טלמטריה נכנסים. זה קורה במהלך שלב הסטרימינג, בדרך כלל לפני שתהליכי העשרת הנתונים ברקע (כמו GeoIP או ASN) מסתיימים.

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

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

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

rule outbound_ip_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $outbound_ip_count = count($e.target.ip) // yields 2.

  condition:
    $e
}

רשומות של אירועים: לפני ואחרי ביטול ההטמעה

הטבלאות בקטע הזה מדגימות איך אירוע בודד שמכיל מערך של כתובות IP הופך לשתי רשומות נפרדות.

לפני ביטול ההטמעה

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

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps [192.0.2.20, 192.0.2.28]

אחרי ביטול ההטמעה

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

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps 192.0.2.20
aaaaaaaaa Google SecOps 192.0.2.28

שדות חוזרים בתוך שדות (מכפלה קרטזית)

כשכלל מפנה לשדה חוזר שמוטמע בתוך שדה אחר, כמו security_results.action, ביטול ההטמעה מתרחש בשתי הרמות (הורה וצאצא) בו-זמנית. התוצאה היא מכפלה קרטזית של כל הרכיבים.

בדוגמה הבאה, אירוע $e עם שני ערכים חוזרים ב-security_results ושני ערכים חוזרים ב-security_results.actions מפורק לארבעה מופעים.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $security_action_count = count($e.security_results.actions) // yields 4.

  condition:
    $e
}

רשומת אירוע לפני ביטול ההטמעה של רשומות מוטמעות

הרשומה המקורית מאחסנת את הפעולות במבנה של מערך מקונן.

metadata.id principal.application security_results
aaaaaaaaa Google SecOps [ { actions: [ ALLOW, FAIL ] }, { actions: [ CHALLENGE, BLOCK ] } ]

רשומות של אירועים אחרי ביטול קינון של קינון

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

metadata.id principal.application security_results.actions
aaaaaaaaa Google SecOps אישור
aaaaaaaaa Google SecOps נכשל
aaaaaaaaa Google SecOps אתגר
aaaaaaaaa Google SecOps חסימה

השפעה על שדות לא קשורים

ההתנהגות הזו של ביטול ההתאמה בהערכת הכלל יכולה להוביל לצבירת תוצאות לא צפויות, כשהכלל מפנה לשדה חוזר אחד או יותר עם שדה הורה שהוא גם שדה חוזר. צבירות לא ייחודיות כמו sum(),‏ array() ו-count() לא יכולות להביא בחשבון ערכים כפולים בשדות אחרים באותו אירוע שנוצרו על ידי התנהגות ביטול ההטמעה.

בדוגמה הבאה, לאירוע $e יש שם מארח אחד (google.com), אבל התוצאה (hostnames) צוברת ארבעה מופעים לא מקוננים של אותו אירוע $e, לכל אחד מהם יש ערך principal.hostname כפול. התוצאה הזו מניבה ארבעה שמות מארחים (במקום אחד) בגלל ביטול ההטמעה של ערכים חוזרים ב-security_results.actions.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $hostnames = array($e.principal.hostname) // yields 4.
    $security_action_count = count($e.security_results.action) // yields 4.

  condition:
    $e
}

רשומת אירוע לפני ביטול ההטמעה עם שדות לא קשורים

שם המארח הוא ערך יחיד, אבל הוא מופיע לצד תוצאות האבטחה החוזרות.

metadata.id principal.application principal.hostname security_results
aaaaaaaaa Google SecOps google.com [ { action: [ ALLOW, FAIL ] }, { action: [ CHALLENGE, BLOCK ] } ]

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

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

metadata.id principal.application principal.hostname security_results.action
aaaaaaaaa Google SecOps google.com אישור
aaaaaaaaa Google SecOps google.com נכשל
aaaaaaaaa Google SecOps google.com אתגר
aaaaaaaaa Google SecOps google.com חסימה

פתרון עקיף להתנהגות של unnesting

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

  • max()
  • min()
  • array_distinct()
  • count_distinct()

צבירת תוצאות עם כמה משתני אירועים

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

events:
  $e1.field = $e2.field
  $e2.somefield = $ph

match:
  $ph over 1h

outcome:
   $some_outcome = sum(if($e1.otherfield = "value", 1, 0))

condition:
  $e1 and $e2
event1:
  // UDM event 1
  field="a"
  somefield="d"

event2:
  // UDM event 2
  field="b"
  somefield="d"

event3:
  // UDM event 3
  field="c"
  somefield="d"

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

1: $e1 = event1, $e2 = event2
2: $e1 = event1, $e2 = event3
3: $e1 = event2, $e2 = event1
4: $e1 = event2, $e2 = event3
5: $e1 = event3, $e2 = event1
5: $e1 = event3, $e2 = event2

התוצאה היא סכום מקסימלי אפשרי של 6, למרות ש-$e2 יכול להתאים רק ל-3 אירועים נפרדים.

ההגדרה הזו משפיעה על הסכום, הספירה והמערך. במקרה של ספירה ומערך, אפשר לפתור את הבעיה באמצעות count_distinct או array_distinct, אבל אין פתרון עקיף לסכום.

סוגריים בתחילת ביטוי

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

התחביר לא תקין

parsing: error with token: ")"
invalid operator in events predicate

הדוגמה הבאה יוצרת את סוג השגיאה הזה:

($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600 > 1

וריאציות תחביר תקינות

הגרסאות הבאות של התחביר מחזירות את אותה תוצאה, אבל עם תחביר תקין:

$event.metadata.ingested_timestamp.seconds / 3600 -
$event.metadata.event_timestamp.seconds / 3600 > 1
    1 / 3600 * ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) > 1
    1 < ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600

מערך האינדקסים בתוצאה דורש צבירה

אי אפשר להוסיף לאינדקס ישירות מערך בקטע outcome של שדות חוזרים. הוא דורש משתנה פלייסהולדר זמני.

outcome:
  $principal_user_dept = $suspicious.principal.user.department[0]

דרך לעקיפת הבעיה

מתעדים את אינדקס המערך הספציפי במשתנה של פלייסהולדר בקטע events, ואז מפנים לפלייסהולדר הזה בתוצאה.

events:
  $principal_user_dept = $suspicious.principal.user.department[0]

outcome:
  $principal_user_department = $principal_user_dept

תנאי OR עם אי-קיום

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

לדוגמה, תחביר הכלל הבא יכול להתאים לאירועים שמכילים את $event_a.field = "something", למרות שהוא לא אמור להתאים להם:

events:
     not ($event_a.field = "something" **or** $event_b.field = "something")
condition:
     $event_a and #event_b >= 0

דרך לעקיפת הבעיה

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

events:
  not ($event_a.field = "something")
  not ($event_b.field = "something")

condition:
  $event_a and #event_b >= 0

פעולות חשבון עם שדות אירועים לא חתומים

אם משתמשים בליטרל של מספר שלם בפעולה אריתמטית (+,‏ -,‏ *) או בפעולת מודולו (%) עם שדה UDM של מספר שלם ללא סימן, מקבלים שגיאה. ערכים מספריים שלמים רגילים מוגדרים כברירת מחדל כמספרים שלמים חתומים בטווח 64 ביט (INT64), שלא תואמים לשדות UDM שמוגדרים כמספרים שלמים לא חתומים בטווח 64 ביט (UINT64), כמו network.received_bytes,‏ network.sent_bytes ו-principal.file.size.

האילוץ הזה חל על שני החלקים events ו-outcome, כולל בתוך צבירות sum() או max() וביטויי חלוקה. בודק התחביר של YARA-L מתייחס למספרים שלמים עם סימן ולמספרים שלמים בלי סימן כסוג int כללי. כתוצאה מכך, כלל שמשלב שדות UDM מסוג UINT64 וערכים מספריים שלמים מסוג INT64 עשוי לעבור את אימות התחביר בזמן השמירה, אבל להיכשל במהלך הפעלת הכלל או כשלוחצים על Run Test. אם הכלל נכשל, נוצרת שגיאה כללית מסוג "שגיאה בכלל" (cannot complete [arithmetic/mod] operation between unsigned and signed integer).

לדוגמה, ההשוואה הבאה של events עוברת את אימות התחביר כששומרים אותה, אבל נכשלת במהלך ההפעלה כי $e.network.received_bytes (UINT64) מוכפל בערך המילולי של המספר השלם החתום 2 (INT64):

events:
  $total_bytes = $e.network.total_bytes
  $total_bytes = $e.network.received_bytes * 2

פתרונות עקיפים

כדי לפתור את חוסר ההתאמה הזה, אפשר להשתמש באחת מהשיטות הבאות:

  • המרה מפורשת של מספר שלם (cast.as_int() או cast.as_uint()): ממירים את שדה ה-UDM ללא סימן למספר שלם עם סימן באמצעות cast.as_int(), או ממירים את הליטרל של המספר השלם למספר שלם ללא סימן באמצעות cast.as_uint(). השיטה הזו מתאימה כשצריך תוצאה של מספר שלם או כשמשתמשים באופרטור מודולו (%), שמקבל רק אופרנדים של מספרים שלמים.
  • אילוץ נקודה צפה (floating-point coercion): מאלצים את הקבוע של המספר השלם להתנהג כמו float באמצעות ליטרל של נקודה צפה, כמו 2.0 או 100.0. בביטויים פשוטים בלי אופרטורים אחרים של חילוק באותה שורה, אפשר גם להשתמש בפעולת חילוק, כמו (2/1). בביטויים שכבר מכילים אופרטורים של חילוק (/), השתמשו בערכים מילוליים של נקודה צפה (floating-point) או ב-cast.as_int() במקום בהמרה כפויה של חילוק (N/1). אם יש כמה תווים של / באותה שורה, יכול להיות שהם יפורשו כמחרוזת מילולית של ביטוי רגולרי, מה שיגרום לשגיאת ניתוח במהלך ההידור או לשיבוש של הדגשת התחביר בעורך הכללים.

פתרון עקיף בקטע events

כדי לתקן את השגיאה בקטע events, צריך להשתמש ב-cast.as_int(), בערך מילולי של נקודה צפה או בהמרה של חילוק:

  • שימוש ב-cast.as_int():

    events:
      $total_bytes = $e.network.total_bytes
      $total_bytes = cast.as_int($e.network.received_bytes) * 2
    
  • שימוש בערך מילולי של נקודה צפה:

    events:
      $total_bytes = $e.network.total_bytes
      $total_bytes = $e.network.received_bytes * 2.0
    
  • שימוש באילוץ חלוקה:

    events:
      $total_bytes = $e.network.total_bytes
      $total_bytes = $e.network.received_bytes * (2/1)
    

פתרון עקיף בקטע outcome

הביטוי הבא של outcome נשמר בלי שגיאת תחביר, אבל נכשל בזמן הריצה כי sum($e.network.sent_bytes) ו-sum($e.network.received_bytes) מחזירים ערכי UINT64 שמשולבים עם הערכים המילוליים החתומים INT64, 100 ו-1:

outcome:
  // Saves, but fails at runtime:
  $upload_ratio_pct = sum($e.network.sent_bytes) * 100 / (sum($e.network.received_bytes) + 1)

צריך לשכתב את הביטוי באמצעות ערכים מילוליים של נקודה צפה או cast.as_int() כדי שהוא יישמר ויפעל בלי שגיאות:

  • שימוש בערכים מילוליים של נקודה צפה:

    outcome:
      $upload_ratio_pct = sum($e.network.sent_bytes) * 100.0 / (sum($e.network.received_bytes) + 1.0)
    
  • שימוש ב-cast.as_int():

    outcome:
      $upload_ratio_pct = sum(cast.as_int($e.network.sent_bytes)) * 100 / (sum(cast.as_int($e.network.received_bytes)) + 1)
    

העשרת GeoIP ומודל עקביות הדרגתי

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

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

לדוגמה, שימו לב לאירוע הכלל הבא:

$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

הכלל מסתמך על העובדה שהאירוע חייב לכלול את $e.principal.ip_geo_artifact.network.asn = "16509" וגם את $e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom", ששניהם שדות מועשרים. אם העשרת הנתונים לא תושלם בזמן, הכלל יפיק תוצאה חיובית כוזבת.

כדי להימנע מכך, עדיף להשתמש בבדיקה הבאה:

$e.principal.ip_geo_artifact.network.asn != "" AND
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region != "" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

הכלל הזה מבטל את האפשרות שהאירוע יופעל על ידי כתובות IP עם ASN 16509 אבל מחוץ לבריטניה. כך אפשר לשפר את הדיוק הכולל של הכלל.

כך פותרים בעיות שקשורות להשהיה בהעשרת הנתונים.

פתרון בעיות

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

אירועים עתידיים

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

השהיה בהעשרה

כדי לחשוף התראות ראשוניות כמה שיותר מהר, Google SecOps נותן עדיפות למהירות ההטמעה. עם זאת, תהליכי העשרה ברקע, כמו פתרון מטא-נתונים של GeoIP, ASN או UDM, פועלים לפי מודל עקביות הדרגתי.

הרצה ראשונית (T₀)

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

  • תוצאות שליליות כוזבות (עיכוב בזיהוי): זו תוצאה נפוצה. אם כלל תלוי בשדה מועשר כדי להפעיל (לדוגמה, target.user.department == "Finance"), והשדה הזה הוא null, הכלל לא תואם במהלך ההפעלה הראשונית.

  • תוצאות חיוביות מוטעות (החרגה שהוחמצה): אם הכלל שלכם משתמש בשדות מועשרים כדי לסנן פעילות תקינה ידועה (לדוגמה, NOT target.ip_geo_country == "US"), יכול להיות שהכלל יפעיל תוצאה חיובית מוטעית כי נתוני ה"החרגה" עדיין לא הוחלו.

הרצות של התאמה

ההרצות האלה ברקע מעריכות מחדש את הנתונים אחרי עיכוב (לדוגמה, 4 שעות או 30 שעות). הפעולה הזו "מתקנת" את מצבי הזיהוי באופן הבא:

  • זיהויים מאוחרים: אירועים שהיו "שליליים כוזבים" ב-T₀, ועכשיו מייצרים זיהוי אחרי שההעשרה הושלמה.

  • תיקון: כל התוצאות החיוביות הכוזבות ב-T₀ נשארות במערכת, אבל הנתונים המועשרים במלואם גלויים בכלי לצפייה ב-UDM לצורך מיון ידני.

הרצת בדיקת פערים

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

תיקון שגיאות

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

שגיאה תיאור תיקון מעשי
כשל בהחרגה כלל מופעל למרות החרגה (לדוגמה, != "ASN_123") כי השדה היה ריק במהלך ההפעלה הראשונית. מוסיפים בדיקה של ערך שאינו null לקטע האירועים כדי לוודא שהנתונים מועשרים לפני ההערכה, לדוגמה:

$e.principal.ip_geo_artifact.network.asn != ""
השוואה בין משחק בשידור חי למשחק אימון כללים פעילים מפעילים התראות, אבל הפעלת בדיקה על אותם נתונים מציגה את ההודעה "No Results". מוסיפים את $e.field != "", שבודק את כל השדות המועשרים (GeoIP,‏ ASN,‏ File Path) כדי לסנכרן את ההתנהגות בזמן אמת ובהיסטוריה.
חסרים מטא-נתונים הזיהויים מופיעים במרכז הבקרה עם שדות GeoIP או File Path ריקים. זה צפוי בהרצות של T0. כדי לפתור את הבעיה, צריך לכלול בדיקת field != "" או להגדיר השהיית הסדרה בתזמון הכלל כדי לאפשר יותר זמן להטמעה.

אימות ובדיקה

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

  1. זיהוי התיוג: מאתרים זיהוי שלדעתכם הוא תוצאה חיובית כוזבת. בעמודה סוג הזיהוי, מחפשים את הסמל <span class="material-icons">lightbulb</span>. התראות בלי הסמל הזה הן מההרצה הראשית, שבה העיכוב בהעשרה הוא הכי נפוץ.

  2. עדכון הלוגיקה של הכלל: מוסיפים בדיקת field != "" לכל הנקודות על הגרף של הנתונים המועשרים שבהן משתמשים בלוגיקה.
    דוגמה (נתיב קובץ):
    $e.target.process.parent_process.file.full_path != ""

  3. בדיקה ואימות:

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

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

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