收集 HackerOne 記錄
本文說明如何設定 HackerOne,透過 Webhook 將記錄檔推送至 Google Security Operations。
HackerOne 是安全漏洞協調和錯誤獎金平台,可讓機構與安全研究人員合作,找出並修復安全漏洞。這個平台提供錯誤獎金計畫、安全漏洞揭露計畫、滲透測試,以及整個軟體開發生命週期的持續安全性測試。
事前準備
請確認您已完成下列事前準備事項:
- Google SecOps 執行個體
- HackerOne 方案 (專業版或企業版,只有這些版本提供 Webhook)
- HackerOne 計畫設定的管理員存取權
在 Google SecOps 中建立 Webhook 動態饋給
建立動態饋給
- 依序前往「SIEM 設定」>「動態饋給」。
- 按一下「新增動態消息」。
- 在下一個頁面中,按一下「設定單一動態饋給」。
- 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如
HackerOne Vulnerability Reports)。 - 選取「Webhook」做為「來源類型」。
- 選取「HackerOne」做為「記錄類型」。
- 點選「下一步」。
- 指定下列輸入參數的值:
- 分割分隔符 (選填):留空。每個 Webhook 要求都包含單一 JSON 事件。
- 資產命名空間:資產命名空間。
- 擷取標籤:要套用至這個動態饋給事件的標籤。
- 點選「下一步」。
- 在「Finalize」(完成) 畫面中檢查新的動態饋給設定,然後按一下「Submit」(提交)。
產生並儲存密鑰
建立動態饋給後,您必須產生驗證用的密鑰:
- 在動態消息詳細資料頁面中,按一下「產生密鑰」。
- 對話方塊會顯示密鑰。
- 複製並妥善儲存密鑰。
取得動態饋給端點網址
- 前往動態消息的「詳細資料」分頁。
- 在「端點資訊」部分,複製「動態消息端點網址」。
網址格式為:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate或
https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate請儲存這個網址,以供後續步驟使用。
按一下 [完成]。
建立 Google Cloud API 金鑰
Chronicle 需要 API 金鑰才能進行驗證。在 Google Cloud 控制台中建立受限制的 API 金鑰。
建立 API 金鑰
- 前往 Google Cloud 控制台的「憑證」頁面。
- 選取專案 (與 Chronicle 執行個體相關聯的專案)。
- 依序按一下「建立憑證」>「API 金鑰」。
- 系統會建立 API 金鑰,並在對話方塊中顯示。
- 按一下「編輯 API 金鑰」即可限制金鑰。
限制 API 金鑰
- 在「API 金鑰」設定頁面中:
- 名稱:輸入描述性名稱 (例如
Chronicle HackerOne Webhook API Key)。
- 名稱:輸入描述性名稱 (例如
- 在「API 限制」下方:
- 選取「Restrict key」(限制金鑰)。
- 在「選取 API」清單中,搜尋並選取「Google SecOps API」 (或「Chronicle API」)。
- 按一下 [儲存]。
- 從頁面頂端的「API key」(API 金鑰) 欄位複製 API 金鑰值。
安全儲存 API 金鑰。
設定 HackerOne Webhook
建構 Webhook 網址
合併 Chronicle 端點網址和 API 金鑰:
<ENDPOINT_URL>?key=<API_KEY>範例:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
在 HackerOne 中建立 Webhook
- 登入 HackerOne,然後前往您的計畫。
- 前往「參與度」,點按要設定的計畫的 Kebab 選單,然後按一下「設定」。
- 依序前往「自動化」> Webhook。
- 按一下「New webhook」。
- 請提供下列設定詳細資料:
- 酬載網址:貼上上述包含 API 金鑰的完整端點網址。
- 密鑰:貼上從 Chronicle 動態饋給建立作業取得的密鑰。
- 選取要觸發 Webhook 的事件:選擇下列其中一個選項:
- 傳送所有內容:所有事件都會觸發 Webhook。
- 讓我指定個別事件:選取要傳送至 Chronicle 的特定事件。建議用於安全監控的事件:
- report_created:駭客提交新的安全漏洞報告時
- report_triaged:報表經過分類時
- report_resolved:檢舉單解決時
- report_bounty_awarded:獲得獎金時
- report_swag_awarded:頒發商品時
- program_hacker_joined:駭客加入計畫時
- program_hacker_left:駭客退出計畫時
- 按一下 [Add Webhook]。
測試 Webhook
- 在 Webhook 設定頁面中,選取「測試要求」,將範例要求傳送至設定的 Payload URL。
- 確認回應為 HTTP 200。
- 在 1 到 2 分鐘內檢查 Chronicle 動態消息中的測試事件。
確認 Webhook 運作正常
檢查 HackerOne Webhook 狀態
- 登入 HackerOne 控制台。
- 前往「參與度」,按一下計畫的三點選單,然後點選「設定」。
- 依序前往「自動化」> Webhook。
- 按一下 Webhook 即可查看詳細資料。
- 在「最近的傳送」部分下方,確認最近的傳送作業顯示成功狀態 (HTTP 200)。
- 按一下任一傳送作業,即可查看 POST 酬載要求。
查看 Chronicle 動態消息狀態
- 前往 Chronicle 的「SIEM 設定」>「動態饋給」。
- 找出 HackerOne 網路鉤子動態消息。
- 檢查「狀態」欄 (應為「有效」)。
- 檢查「收到的事件」計數 (應會遞增)。
- 檢查「上次成功時間」時間戳記 (應為最近的時間)。
在 Chronicle 中驗證記錄
- 依序前往「搜尋」>「UDM 搜尋」。
請使用下列查詢:
metadata.vendor_name = "HACKERONE" AND metadata.product_name = "HACKERONE"將時間範圍調整為過去 1 小時。
確認結果中顯示事件。
驗證方式參考資料
Chronicle 網頁掛鉤動態消息支援多種驗證方法。HackerOne 網路鉤子會結合查詢參數和簽章驗證。
方法 1:使用查詢參數和簽章驗證 (建議用於 HackerOne)
HackerOne 會將 Webhook 傳送至設定的酬載網址。驗證作業由下列項目處理:
- 網址中的 API 金鑰:Chronicle API 金鑰會附加至酬載網址,做為查詢參數。
密鑰簽章驗證:HackerOne 會產生 X-H1-Signature 標頭,其中包含以設定的密鑰簽署的要求主體 HMAC SHA256 十六進位摘要。
網址格式:
<ENDPOINT_URL>?key=<API_KEY>要求格式:
POST <ENDPOINT_URL>?key=<API_KEY> HTTP/1.1 Content-Type: application/json X-H1-Signature: sha256=<HMAC_HEXDIGEST> X-H1-Event: <EVENT_TYPE> X-H1-Delivery: <DELIVERY_ID> { "data": { "activity": {...}, "report": {...} } }
優點:
- 雙重驗證:用於存取 Chronicle 的 API 金鑰,以及用於驗證酬載的簽章
- HackerOne 提供內建簽章產生功能
- 安全地驗證酬載完整性
驗證簽章
HackerOne 會在每個 Webhook 要求中加入下列標頭:
- X-H1-Signature:要求主體的 HMAC SHA256 十六進位摘要 (格式:
sha256=<hexdigest>) - X-H1-Event:觸發 Webhook 的事件類型
- X-H1-Delivery:配送作業的專屬 ID
- X-H1-Signature:要求主體的 HMAC SHA256 十六進位摘要 (格式:
如要驗證接收端點上的簽名,請按照下列步驟操作:
import hmac import hashlib def validate_request(request_body, secret, signature): _, digest = signature.split('=') generated_digest = hmac.new( secret.encode(), request_body.encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(digest, generated_digest)
Webhook 事件類型
HackerOne 支援下列 Webhook 事件類型:
| 事件類型 | 說明 |
|---|---|
| report_created | 駭客提交新的安全漏洞報告時觸發 |
| report_triaged | 在報告經過分類時觸發 |
| report_resolved | 在檢舉單解決時觸發 |
| report_bounty_awarded | 在為報告核發獎金時觸發 |
| report_swag_awarded | 在為報告頒發贈品時觸發 |
| report_became_public | 報表設為公開時觸發 |
| program_hacker_joined | 駭客加入計畫時觸發 |
| program_hacker_left | 駭客離開計畫時觸發 |
UDM 對應表
| 記錄欄位 | UDM 對應 | 邏輯 |
|---|---|---|
| attributes.cleared、attributes.rules_of_engagement_signed、attributes.identity_verified、attributes.background_checked、attributes.citizenship_verified、attributes.residency_verified、type、attributes.title、attributes.main_state、attributes.state、relationships.reporter.data.type、relationships.reporter.data.attributes.reputation、relationships.reporter.data.attributes.signal、relationships.reporter.data.attributes.impact、relationships.reporter.data.attributes.disabled、relationships.reporter.data.attributes.profile_picture.62x62、relationships.reporter.data.attributes.profile_picture.82x82、relationships.reporter.data.attributes.profile_picture.110x110、relationships.reporter.data.attributes.profile_picture.260x260、relationships.reporter.data.attributes.hackerone_triager、relationships.program.data.id、relationships.program.data.type、relationships.program.data.attributes.handle、relationships.severity.data.type、relationships.severity.data.attributes.rating、relationships.severity.data.attributes.author_type、relationships.severity.data.attributes.calculation_method、relationships.weakness.data.id、relationships.weakness.data.type、relationships.weakness.data.attributes.name、relationships.weakness.data.attributes.description、relationships.weakness.data.attributes.external_id、relationships.structured_scope.data.id、relationships.structured_scope.data.type、relationships.structured_scope.data.attributes.asset_type、relationships.structured_scope.data.attributes.eligible_for_bounty、relationships.structured_scope.data.attributes.eligible_for_submission、relationships.structured_scope.data.attributes.instruction、relationships.structured_scope.data.attributes.max_severity、relationships.structured_scope.data.attributes.confidentiality_requirement、relationships.structured_scope.data.attributes.integrity_requirement、relationships.structured_scope.data.attributes.availability_requirement、relationships.inboxes.data.id、relationships.inboxes.data.type、relationships.inboxes.data.attributes.name、relationships.inboxes.data.attributes.type | additional.fields | 合併為鍵/值標籤 |
| 時間戳記 | metadata.event_timestamp | 使用日期篩選器剖析,格式為 yyyy-MM-dd'T'HH:mm:ss.SSSZ |
| metadata.event_type | 如果 has_principal 為 true,則設為「STATUS_UPDATE」;如果 has_principal_user_user 為 true,則設為「USER_UNCATEGORIZED」;否則設為「GENERIC_EVENT」 | |
| id | metadata.product_log_id | 直接複製值 |
| relationships.structured_scope.data.attributes.asset_identifier | principal.asset.asset_id | 開頭為「ASSET:」 |
| attributes.email_alias | principal.user.email_addresses | 已合併 |
| relationships.reporter.data.id | principal.user.employee_id | 直接複製值 |
| relationships.reporter.data.attributes.name | principal.user.first_name | 直接複製值 |
| attributes.username、relationships.reporter.data.attributes.username | principal.user.user_display_name | 如果 relationships.reporter.data.attributes.username 不為空,則為該值,否則為 attributes.username |
| relationships.severity.data.attributes.user_id | principal.user.userid | 直接複製值 |
| relationships.severity.data.id | security_result.rule_id | 直接複製值 |
| relationships.severity.data.attributes.max_severity | security_result.severity | 已轉換為大寫 |
| attributes.vulnerability_information | security_result.summary | 直接複製值 |
還有其他問題嗎?向社群成員和 Google SecOps 專業人員尋求答案。