收集 ServiceNow Security 記錄

支援的國家/地區:

本文說明如何使用 Webhook 資訊提供,將 ServiceNow 安全性事件傳送至 Google Security Operations。ServiceNow Security 剖析器適用於 ServiceNow 執行個體安全中心安全性事件,例如登入失敗、SNC 登入、管理員登入、模擬和安全性提升 (請參閱「ServiceNow 執行個體安全中心安全性事件」)。ServiceNow 整合功能會將每個事件以 JSON 格式發布至 Google SecOps 網頁掛鉤端點,剖析器會將事件正規化為統合資料模型 (UDM)。

剖析器會辨識五個事件值:Failed LoginAdmin LoginSNC LoginImpersonationSecurity Elevation。每個值都對應至 sysevent 佇列中已註冊的 ServiceNow 事件。這份文件會建立 Webhook 動態消息、POST 到動態消息的指令碼包含項目,以及在相符的 sysevent 記錄上觸發並呼叫指令碼包含項目的四個指令碼動作。

完成這項一次性設定後,ServiceNow 會自動將每個新的安全性事件轉送至 Google SecOps。管理員不需採取進一步行動。

事前準備

請確認您已完成下列事前準備事項:

  • Google SecOps 執行個體。
  • ServiceNow 執行個體,以及具備 admin 角色或權限的使用者帳戶,可存取「System Definition」(系統定義) >「Script Includes」(指令碼包含)、「System Properties」(系統屬性),以及「System Policy」(系統政策) >「Events」(事件) >「Script Actions」(指令碼動作) 和「Registry」(登錄)
  • 現有的 ServiceNow 執行個體安全中心啟用作業。ISC 已終止銷售,無法在新執行個體上啟用。
  • Google Google Cloud 控制台的特殊權限 (用於建立 API 金鑰)。

在 Google SecOps 中建立 Webhook 動態饋給

以下各節說明如何在 Google SecOps 中建立 Webhook 資訊提供。

建立動態饋給

  1. 依序前往「SIEM 設定」>「動態饋給」
  2. 按一下「新增動態消息」
  3. 在下一個頁面中,按一下「設定單一動態饋給」
  4. 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如 ServiceNow Security Events)。
  5. 選取「Webhook」做為「來源類型」
  6. 選取「ServiceNow Security」做為「記錄類型」
  7. 點選「下一步」
  8. 指定下列輸入參數的值:

    • 分割分隔符號:如果整合服務在每個要求中傳送多個 JSON 事件,請輸入 \n。如果每個要求都包含單一事件,請留空。
    • 資產命名空間資產命名空間
    • 擷取標籤:套用至這個動態饋給事件的標籤。
  9. 點選「下一步」

  10. 在「Finalize」(完成) 畫面中檢查新的動態饋給設定,然後按一下「Submit」(提交)

產生並儲存密鑰

  1. 在動態饋給詳細資料頁面中,按一下「產生密鑰」
  2. 複製並儲存密鑰,並妥善存放在安全的位置。

取得動態消息端點網址

  1. 前往動態消息的「詳細資料」分頁。
  2. 在「端點資訊」部分,複製「動態消息端點網址」。網址格式為:

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

    或是區域端點:

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  3. 請儲存這個網址,稍後會用到。

  4. 按一下 [完成]

建立 Google Cloud API 金鑰

  1. 前往 Google Google Cloud 控制台的「憑證」頁面
  2. 選取與 Google SecOps 執行個體相關聯的專案。
  3. 依序按一下「建立憑證」>「API 金鑰」
  4. 按一下「編輯 API 金鑰」即可限制金鑰。
  5. 在「Name」(名稱) 欄位中輸入描述性名稱 (例如 ServiceNow Webhook API Key)。
  6. 在「API 限制」下方:

    1. 選取「Restrict key」(限制金鑰)
    2. 在「選取 API」清單中,選取「Google SecOps API」
  7. 按一下 [儲存]

  8. 複製 API 金鑰,並儲存在安全地點。

在 ServiceNow 中儲存 Google SecOps 憑證

將端點網址和憑證儲存為 ServiceNow 系統屬性,這樣整合程式碼就不會包含密鑰。

  1. 在 ServiceNow 中,依序前往「System Properties」(系統屬性) > sys_properties.list
  2. 按一下「新增」,然後提供下列設定詳細資料:

    • Name (名稱):x_chronicle.endpoint_url
    • :貼上動態消息端點網址。
    • 「類型」string
  3. 按一下「提交」

  4. 按一下「新增」,然後提供下列設定詳細資料:

    • Name (名稱):x_chronicle.api_key
    • :貼上 Google Cloud API 金鑰。
    • 「類型」password2
  5. 按一下「提交」

  6. 按一下「新增」,然後提供下列設定詳細資料:

    • Name (名稱):x_chronicle.secret_key
    • :貼上 Google SecOps 摘要資訊的密鑰。
    • 「類型」password2
  7. 按一下「提交」

建立 Webhook 公用程式指令碼包含項目

這個指令碼會使用 ServiceNow sn_ws.RESTMessageV2 範圍 API,將 JSON 酬載發布至 Google SecOps Webhook 端點。API 金鑰和私密金鑰會以 HTTP 標頭的形式傳送。

  1. 前往「系統定義」>「指令碼包含」
  2. 點選「New」(新增)
  3. 請提供下列設定詳細資料:

    • Name (名稱):ChronicleWebhookUtil
    • API 名稱ChronicleWebhookUtil
    • 用戶端可呼叫:取消勾選
    • 有效:已勾選
  4. 在「指令碼」欄位中,輸入下列程式碼:

    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 會隨附這項整合功能使用的五個事件,但建議您確認,因為如果缺少項目,系統不會產生錯誤,且 Script Action 永遠不會執行。

  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 佇列時,系統會執行指令碼動作、讀取事件參數,並呼叫 ChronicleWebhookUtil 來 POST 酬載。

剖析器會對應至下列 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 或其他高權限角色。

loginlogin.failedparm1 設為使用者名稱,並將 parm2 設為來源 IP。其他事件會遵循相同的 parm1/parm2 慣例,但確切內容取決於 ServiceNow 版本。開啟每個事件的登錄項目,確認「參數」說明與稍後說明的指令碼相符。如果登錄檔不同,請調整 parm1parm2 參照。

建立登入失敗指令碼動作

  1. 依序前往「系統政策」>「事件」>「指令碼動作」
  2. 點選「New」(新增)
  3. 請提供下列設定詳細資料:

    • Name (名稱):Chronicle - Failed Login
    • 活動名稱login.failed
    • 有效:已勾選
  4. 在「指令碼」欄位中,輸入下列程式碼:

    (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. 按一下「提交」

建立登入指令碼動作

這項指令碼動作會在每次成功登入時觸發,且只會在登入使用者具有 adminsnc_external 角色時轉送記錄。event 欄位會相應設定。

  1. 依序前往「系統政策」>「事件」>「指令碼動作」
  2. 點選「New」(新增)
  3. 請提供下列設定詳細資料:

    • Name (名稱):Chronicle - Login
    • 活動名稱login
    • 有效:已勾選
  4. 在「指令碼」欄位中,輸入下列程式碼:

    (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. 點選「New」(新增)
  3. 請提供下列設定詳細資料:

    • Name (名稱):Chronicle - Impersonation
    • 活動名稱impersonation.start
    • 有效:已勾選
  4. 在「指令碼」欄位中,輸入下列程式碼:

    (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. 點選「New」(新增)
  3. 請提供下列設定詳細資料:

    • Name (名稱):Chronicle - Security Elevation
    • 活動名稱security.elevated_role.enabled
    • 有效:已勾選
  4. 在「指令碼」欄位中,輸入下列程式碼:

    (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. 在「執行指令碼」欄位中,輸入下列其中一行,然後按一下「執行指令碼」

    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 位址登入。
  • 模擬:從管理員帳戶模擬其他使用者。
  • 安全性提升:從具有 admin 角色的使用者提升至 security_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 中,對 metadata.vendor_name = "SERVICENOW"metadata.product_name = "SERVICENOW_SECURITY" 執行 UDM 搜尋。
  4. 確認事件顯示的 metadata.event_type 已設為 USER_LOGINUSER_CHANGE_PERMISSIONS,且 principal.user.userid 已填入。

驗證方法參考資料

Google SecOps Webhook 摘要會將 API 金鑰和私密金鑰視為 HTTP 標頭或網址查詢參數。本指南使用標頭方法,因為 sn_ws.RESTMessageV2 支援自訂標頭,可避免憑證出現在網址和伺服器存取記錄中。

本指南使用的標題:

  • X-goog-api-key:Google SecOps API 的 Google Cloud API 金鑰。
  • X-Webhook-Access-Key:Google SecOps 產生的動態饋給私密金鑰。

如果整合無法傳送自訂標頭,請改為將憑證附加至端點網址:

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

Webhook 限制和最佳做法

限制
要求大小上限 4 MB
每秒查詢次數 (QPS) 上限 15,000
要求逾時 30 秒
重試行為 自動執行指數輪詢

如要控制數量,請只傳送偵測作業需要的安全性事件,並在來源大量產生事件時,使用 \n 分隔符號,在每個要求中批次處理多個事件。

如要進一步瞭解 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 專業人員尋求答案。