איסוף יומני אבטחה של ServiceNow

נתמך ב:

במאמר הזה מוסבר איך לשלוח אירועי אבטחה של ServiceNow אל Google Security Operations באמצעות פיד של webhook. הכלי לניתוח של ServiceNow Security מיועד לאירועי אבטחה של ServiceNow Instance Security Center, כמו ניסיונות כניסה שנכשלו, כניסות ל-SNC, כניסות של אדמינים, התחזות והעלאת רמת האבטחה (ראו אירועי אבטחה של ServiceNow Instance Security Center). שילוב עם ServiceNow מפרסם כל אירוע כ-JSON לנקודת קצה של webhook ב-Google SecOps, שבה מנתח התחביר מבצע נורמליזציה של האירוע למודל הנתונים המאוחד (UDM).

הכלי לניתוח מזהה חמישה ערכי אירועים: Failed Login,‏ Admin Login,‏ SNC Login,‏ Impersonation ו-Security Elevation. כל ערך תואם לאירוע רשום ב-ServiceNow בתור sysevent. המסמך הזה יוצר פיד webhook, Script Include ששולח POST לפיד וארבע פעולות Script שמופעלות ברשומות sysevent התואמות וקוראות ל-Script Include.

אחרי ההגדרה החד-פעמית הזו, ServiceNow מעביר כל אירוע אבטחה חדש ל-Google SecOps באופן אוטומטי. לא נדרשת פעולה נוספת מצד האדמין.

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

חשוב לוודא שמתקיימות דרישות הסף הבאות:

  • מופע של Google SecOps.
  • מופע של ServiceNow עם חשבון משתמש שיש לו תפקיד admin או הרשאות ל-System Definition > Script Includes,‏ System Properties ו-System Policy > Events > Script Actions ו-Registry.
  • הפעלה קיימת של מרכז האבטחה של ServiceNow Instance. המוצר ISC נמצא בסוף תקופת המכירות שלו, ואי אפשר להפעיל אותו במופעים חדשים.
  • גישה עם הרשאות למסוף Google Google Cloud (ליצירת מפתח API).

יצירת פיד של ווּבּהוּק ב-Google SecOps

בקטעים הבאים מוסבר איך ליצור פיד של webhook ב-Google SecOps.

יצירת הפיד

  1. עוברים אל SIEM Settings > Feeds (הגדרות SIEM > פידים).
  2. לוחצים על הוספת פיד חדש.
  3. בדף הבא, לוחצים על הגדרת פיד יחיד.
  4. בשדה שם הפיד, מזינים שם לפיד (לדוגמה, ServiceNow Security Events).
  5. בוחרים באפשרות Webhook בתור סוג המקור.
  6. בוחרים באפשרות ServiceNow Security בתור סוג היומן.
  7. לוחצים על הבא.
  8. מציינים ערכים לפרמטרים הבאים של הקלט:

    • תו מפריד לפיצול: מזינים \n כשהשילוב שולח יותר מאירוע JSON אחד לכל בקשה. אם כל בקשה מכילה אירוע אחד, משאירים את השדה ריק.
    • מרחב השמות של הנכס: מרחב השמות של הנכס.
    • תוויות להעברה: התווית שמוחלת על האירועים מהפיד הזה.
  9. לוחצים על הבא.

  10. בודקים את ההגדרות של הפיד החדש במסך סיום ולוחצים על שליחה.

יצירה ושמירה של המפתח הסודי

  1. בדף הפרטים של הפיד, לוחצים על יצירת מפתח סודי.
  2. מעתיקים ושומרים את המפתח הסודי במקום מאובטח.

קבלת כתובת ה-URL של נקודת הקצה של הפיד

  1. עוברים לכרטיסייה פרטים של הפיד.
  2. בקטע Endpoint Information, מעתיקים את Feed endpoint URL. הפורמט של כתובת ה-URL הוא:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    

    או, אם משתמשים בנקודת קצה אזורית:

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  3. שומרים את כתובת ה-URL הזו לשלב מאוחר יותר.

  4. לוחצים על סיום.

יצירת מפתח API Google Cloud

  1. נכנסים אל דף האישורים במסוף Google Google Cloud .
  2. בוחרים את הפרויקט שמשויך למופע Google SecOps.
  3. לוחצים על Create credentials > API key.
  4. לוחצים על Edit API key כדי להגביל את המפתח.
  5. בשדה שם, מזינים שם תיאורי (לדוגמה, ServiceNow Webhook API Key).
  6. בקטע הגבלות על ממשקי API:

    1. בוחרים באפשרות הגבלת המקש.
    2. ברשימה Select APIs (בחירת ממשקי API), בוחרים באפשרות Google SecOps API.
  7. לוחצים על Save.

  8. מעתיקים את מפתח ה-API ושומרים אותו במקום מאובטח.

אחסון פרטי הכניסה של Google SecOps ב-ServiceNow

מאחסנים את כתובת ה-URL של נקודת הקצה ואת פרטי הכניסה כמאפייני מערכת של ServiceNow, כדי שקוד השילוב לא יכיל סודות.

  1. ב-ServiceNow, עוברים אל System Properties > sys_properties.list.
  2. לוחצים על New (חדש) ומזינים את פרטי ההגדרה הבאים:

    • Name (שם): x_chronicle.endpoint_url
    • ערך: מדביקים את כתובת ה-URL של נקודת הקצה של הפיד.
    • Type (סוג): string
  3. לוחצים על שליחה.

  4. לוחצים על New (חדש) ומזינים את פרטי ההגדרה הבאים:

    • Name (שם): x_chronicle.api_key
    • ערך: מדביקים את מפתח ה-API של Google Cloud .
    • Type (סוג): password2
  5. לוחצים על שליחה.

  6. לוחצים על New (חדש) ומזינים את פרטי ההגדרה הבאים:

    • Name (שם): x_chronicle.secret_key
    • ערך: מדביקים את מפתח הסוד של פיד Google SecOps.
    • Type (סוג): password2
  7. לוחצים על שליחה.

יצירת סקריפט webhook utility Script Include

הסקריפט הזה כולל פרסום של מטען ייעודי (payload) בפורמט JSON לנקודת הקצה של ה-Webhook של Google SecOps באמצעות ה-API המוגבל להיקף של ServiceNow‏ sn_ws.RESTMessageV2. מפתח ה-API והמפתח הסודי נשלחים ככותרות HTTP.

  1. עוברים אל System Definition > Script Includes.
  2. לוחצים על חדש.
  3. מזינים את פרטי ההגדרה הבאים:

    • Name (שם): ChronicleWebhookUtil
    • שם ה-API: ChronicleWebhookUtil
    • Client callable: לא מסומן
    • פעיל: מסומן
  4. בשדה Script (סקריפט), מזינים את הקוד הבא:

    var ChronicleWebhookUtil = Class.create();
    ChronicleWebhookUtil.prototype = {
        initialize: function() {
            this.endpointURL = gs.getProperty('x_chronicle.endpoint_url');
            this.apiKey = gs.getProperty('x_chronicle.api_key');
            this.secretKey = gs.getProperty('x_chronicle.secret_key');
        },
    
        // payload: a plain object whose keys match the required JSON contract.
        sendEvent: function(payload) {
            try {
                if (!this.endpointURL || !this.apiKey || !this.secretKey) {
                    gs.error('[Chronicle] Missing configuration. Check System Properties: x_chronicle.*');
                    return false;
                }
    
                var request = new sn_ws.RESTMessageV2();
                request.setEndpoint(this.endpointURL);
                request.setHttpMethod('POST');
                request.setRequestHeader('Content-Type', 'application/json');
                request.setRequestHeader('X-goog-api-key', this.apiKey);
                request.setRequestHeader('X-Webhook-Access-Key', this.secretKey);
                request.setRequestBody(JSON.stringify(payload));
    
                var response = request.execute();
                var statusCode = response.getStatusCode();
    
                if (statusCode == 200 || statusCode == 201 || statusCode == 204) {
                    gs.info('[Chronicle] Event sent: ' + payload.event + ' | Status: ' + statusCode);
                    return true;
                }
    
                gs.error('[Chronicle] Failed to send event: ' + payload.event + ' | Status: ' + statusCode + ' | Response: ' + response.getBody());
                return false;
            } catch (ex) {
                gs.error('[Chronicle] Exception sending event: ' + ex.message);
                return false;
            }
        },
    
        type: 'ChronicleWebhookUtil'
    };
    
  5. לוחצים על שליחה.

אימות של רישום האירועים

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

  1. ב-ServiceNow, עוברים אל System Policy > Events > Registry (sysevent_register.list).
  2. מסננים את העמודה שם האירוע לכל אחת מהרשומות הבאות ומוודאים שקיימת רשומה:

    • login
    • login.failed
    • impersonation.start
    • security.elevated_role.enabled
  3. אם חסר רשומה, לוחצים על חדש, מגדירים את השדה שם האירוע לערך החסר, מגדירים את הטבלה ל-Global [global] ולוחצים על שליחה.

יצירת פעולות הסקריפט

כל פעולת סקריפט נרשמת לשם אירוע אחד ב-ServiceNow. כש-ServiceNow מוסיף רשומה תואמת לתור sysevent, הפעולה Script Action מופעלת, קוראת את פרמטרים האירוע וקוראת ל-ChronicleWebhookUtil כדי לפרסם את מטען הייעודי (payload).

הניתוח ממופה לאירועים הבאים ב-ServiceNow:

ערך של מנתח event שם האירוע ב-ServiceNow הטריגר
Failed Login login.failed ניסיון התחברות כושל (כל שיטת אימות).
Admin Login login התחברות מוצלחת של משתמש עם התפקיד admin.
SNC Login login התחברות מוצלחת של משתמש עם התפקיד snc_external.
Impersonation impersonation.start אדמין מתחיל להתחזות למשתמש אחר.
Security Elevation security.elevated_role.enabled משתמש מקבל הרשאת גישה ברמה גבוהה יותר, כמו security_admin.

login ו-login.failed מגדירים את parm1 לשם המשתמש ואת parm2 לכתובת ה-IP של המקור. האירועים האחרים פועלים לפי אותה מוסכמה של parm1/parm2, אבל התוכן המדויק תלוי בגרסת ServiceNow שלכם. פותחים את רשומת הרישום של כל אירוע ומוודאים שהתיאור של Parameters תואם לסקריפט שמתואר בהמשך. אם המרשם שלכם שונה, צריך לשנות את ההפניות parm1 או parm2.

יצירת פעולת סקריפט של התחברות שנכשלה

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

    • Name (שם): Chronicle - Failed Login
    • שם האירוע: login.failed
    • פעיל: מסומן
  4. בשדה Script (סקריפט), מזינים את הקוד הבא:

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Failed Login',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString(),
            ip_address: event.parm2.toString()
        });
    })(current, event);
    
  5. לוחצים על שליחה.

יצירת פעולת סקריפט להתחברות

פעולת הסקריפט הזו מופעלת בכל התחברות מוצלחת ומעבירה את הרשומה רק כשהמשתמש המחובר מחזיק בתפקיד admin או snc_external. השדה event מוגדר בהתאם.

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

    • Name (שם): Chronicle - Login
    • שם האירוע: login
    • פעיל: מסומן
  4. בשדה Script (סקריפט), מזינים את הקוד הבא:

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        var userName = event.parm1.toString();
        var ipAddress = event.parm2.toString();
    
        var user = new GlideRecord('sys_user');
        if (!user.get('user_name', userName)) {
            return;
        }
    
        function hasRole(roleName) {
            var role = new GlideRecord('sys_user_has_role');
            role.addQuery('user', user.sys_id);
            role.addQuery('role.name', roleName);
            role.query();
            return role.next();
        }
    
        var eventValue;
        if (hasRole('snc_external')) {
            eventValue = 'SNC Login';
        } else if (hasRole('admin')) {
            eventValue = 'Admin Login';
        } else {
            return;
        }
    
        new ChronicleWebhookUtil().sendEvent({
            event: eventValue,
            event_created: event.sys_created_on.getValue(),
            user: userName,
            ip_address: ipAddress
        });
    })(current, event);
    
  5. לוחצים על שליחה.

יצירת פעולת סקריפט להתחזות

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

    • Name (שם): Chronicle - Impersonation
    • שם האירוע: impersonation.start
    • פעיל: מסומן
  4. בשדה Script (סקריפט), מזינים את הקוד הבא:

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Impersonation',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString(),       // impersonator
            snc_user: event.parm2.toString()    // impersonated user
        });
    })(current, event);
    
  5. לוחצים על שליחה.

יצירת פעולת סקריפט להעלאת רמת האבטחה

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

    • Name (שם): Chronicle - Security Elevation
    • שם האירוע: security.elevated_role.enabled
    • פעיל: מסומן
  4. בשדה Script (סקריפט), מזינים את הקוד הבא:

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Security Elevation',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString()
        });
    })(current, event);
    
  5. לוחצים על שליחה.

אימות השילוב

אפשר להשתמש באחת מהשיטות הבאות.

אימות באמצעות אירוע סינתטי

כדי לבדוק כל פעולת סקריפט באופן מיידי בלי לחכות לאירוע אבטחה אמיתי, מבצעים את הפעולות הבאות כדי להוסיף את האירוע לתור מסקריפט ברקע:

  1. ב-ServiceNow, עוברים אל System Definition > Scripts - Background.
  2. בשדה Run script (הפעלת סקריפט), מזינים אחת מהשורות הבאות ולוחצים על Run script (הפעלת סקריפט):

    gs.eventQueue('login.failed', null, 'test.user', '203.0.113.45');
    gs.eventQueue('login', null, 'admin', '203.0.113.45');
    gs.eventQueue('impersonation.start', null, 'admin', 'test.user');
    gs.eventQueue('security.elevated_role.enabled', null, 'admin', 'security_admin');
    
  3. מחכים עד דקה עד שהעבודה של המרכז לאירועים תסיים לעבד את התור.

אימות באמצעות אירוע אמיתי

כדי לאמת את השילוב, צריך ליצור אחד מאירועי האבטחה הממופים הבאים ב-ServiceNow:

  • כניסה כושלת: פותחים את /login.do בחלון פרטי בדפדפן ושולחים סיסמה לא תקינה.
  • כניסה לחשבון אדמין: כניסה באמצעות משתמש עם תפקיד admin מכתובת IP ששונה מהכתובת הרגילה שלכם.
  • התחזות: מחשבון אדמין, להתחזות למשתמש אחר.
  • העלאת רמת האבטחה: העלאה לתפקיד security_admin ממשתמש עם התפקיד admin.

אישור ההעברה

  1. ב-ServiceNow, עוברים אל System Policy > Events > Event Log (sysevent.list) ומוודאים שמופיעה רשומה עם שם האירוע המתאים.
  2. ב-ServiceNow, עוברים אל System Logs > System Log > All ומוודאים שמופיעה הודעת מידע [Chronicle] Event sent: ... עם הסטטוס 200,‏ 201 או 204. הודעה עם סמל [Chronicle] Failed to send event או [Chronicle] Exception sending event מציינת בעיה בפרטי הכניסה או בקישוריות.
  3. ב-Google SecOps, מריצים חיפוש UDM עבור metadata.vendor_name = "SERVICENOW" ו-metadata.product_name = "SERVICENOW_SECURITY".
  4. מוודאים שהאירוע מופיע עם metadata.event_type שמוגדר ל-USER_LOGIN או ל-USER_CHANGE_PERMISSIONS, ושהשדה principal.user.userid מאוכלס.

הפניה לשיטות אימות

פידים של webhook ב-Google SecOps מקבלים את מפתח ה-API ואת המפתח הסודי ככותרות HTTP או כפרמטרים של שאילתת URL. במדריך הזה נעשה שימוש בשיטת הכותרות כי sn_ws.RESTMessageV2 תומך בכותרות בהתאמה אישית, וכך פרטי הכניסה לא מופיעים בכתובות URL וביומני גישה לשרת.

כותרות שמופיעות במדריך הזה:

  • X-goog-api-key: מפתח ה-API של Google SecOps API. Google Cloud
  • X-Webhook-Access-Key: מפתח הסודי של הפיד שנוצר על ידי Google SecOps.

אם אי אפשר לשלוח כותרות מותאמות אישית בשילוב, צריך לצרף את פרטי הכניסה לכתובת ה-URL של נקודת הקצה:

<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>

מגבלות ושיטות מומלצות לשימוש ב-Webhook

הגבלה ערך
גודל בקשה מקסימלי ‫4MB
מספר QPS מקסימלי (שאילתות לשנייה) 15,000
זמן קצוב לתפוגה של בקשה ‫30 שניות
התנהגות של ניסיון חוזר אוטומטי עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff)

כדי לשלוט בעוצמת הקול, כדאי לשלוח רק את אירועי האבטחה שהזיהויים שלכם דורשים, ולצרף כמה אירועים לכל בקשה באמצעות התו \n split delimiter אם המקור יוצר אירועים במקבצים.

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

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

טבלת מיפוי UDM

שדה ביומן מיפוי UDM לוגיקה
event extensions.auth.type מיפוי: "Failed Login", "SNC Login", "Admin Login", "Impersonation"MACHINE
event_created metadata.event_timestamp הניתוח הוא yyyy-MM-dd HH:mm:ss
event_type metadata.event_type שם שונה/מיפוי
event metadata.product_event_type מופה כאשר event != ``
ip_address principal.ip ממוזג
user principal.user.userid מופה כאשר user != ``
created_by target.user.userid מופה כאשר created_by != ``
snc_user target.user.userid מופה כאשר snc_user != ``
timestamp event1.idm.read_only_udm.metadata.event_timestamp מופה מיומן השינויים
data.sys_id event1.idm.read_only_udm.metadata.product_log_id מופה מיומן השינויים
data.message_data event1.idm.read_only_udm.metadata.description מופה מיומן השינויים
data.source event1.idm.read_only_udm.principal.resource.name מופה מיומן השינויים
source event1.idm.read_only_udm.additional.fields מופה מיומן השינויים
data.sys_created_on event1.idm.read_only_udm.metadata.collected_timestamp מופה מיומן השינויים
data.sys_created_by event1.idm.read_only_udm.principal.user.userid מופה מיומן השינויים
data.user event1.idm.read_only_udm.principal.user.userid מופה מיומן השינויים
source_instance event1.idm.read_only_udm.principal.namespace מופה מיומן השינויים
data.role event1.idm.read_only_udm.target.resource.attribute.roles מופה מיומן השינויים
data.granted_by event1.idm.read_only_udm.target.user.userid מופה מיומן השינויים
data.level event1.idm.read_only_udm.security_result.severity מופה מיומן השינויים
data.state event1.idm.read_only_udm.security_result.action_details מופה מיומן השינויים

שנה רישום

צפייה ביומן השינויים של כלי הניתוח הזה

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