收集 HackerOne 日志
本文档介绍了如何配置 HackerOne 以使用 Webhook 将日志推送到 Google Security Operations。
HackerOne 是一个漏洞协调和 bug 赏金平台,可将组织与安全研究人员联系起来,以识别和修复安全漏洞。该平台提供 bug 赏金计划、漏洞披露计划、渗透测试以及贯穿整个软件开发生命周期的持续安全测试。
准备工作
确保您满足以下前提条件:
- Google SecOps 实例
- 采用专业版或企业版层级的 HackerOne 计划(Webhook 仅适用于这些层级)
- 对 HackerOne 计划设置的管理员访问权限
在 Google SecOps 中创建 Webhook Feed
创建 Feed
- 依次前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 在下一页上,点击配置单个 Feed。
- 在Feed 名称字段中,输入 Feed 的名称(例如
HackerOne Vulnerability Reports)。 - 选择 Webhook 作为来源类型。
- 选择 HackerOne 作为日志类型。
- 点击下一步。
- 为以下输入参数指定值:
- 拆分分隔符(可选):留空。每个 webhook 请求都包含一个 JSON 事件。
- 资产命名空间:资产命名空间。
- 注入标签:要应用于此 Feed 中事件的标签。
- 点击下一步。
- 在最终确定界面中查看新的 Feed 配置,然后点击提交。
生成并保存密钥
创建 Feed 后,您必须生成用于身份验证的密钥:
- 在 Feed 详情页面上,点击生成密钥。
- 系统会显示一个包含密钥的对话框。
- 复制并妥善保存此密钥。
获取 Feed 端点网址
- 前往 Feed 的详细信息标签页。
- 在端点信息部分,复制 Feed 端点网址。
网址格式为:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate或
https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate保存此网址以供后续步骤使用。
点击完成。
创建 Google Cloud API 密钥
Chronicle 需要 API 密钥才能进行身份验证。在 Google Cloud Console 中创建受限 API 密钥。
创建 API 密钥
- 前往 Google Cloud 控制台的“凭据”页面。
- 选择您的项目(与您的 Chronicle 实例关联的项目)。
- 依次点击创建凭据> API 密钥。
- 系统会创建一个 API 密钥,并在对话框中显示该密钥。
- 点击修改 API 密钥以限制密钥。
限制 API 密钥
- 在 API 密钥设置页面中:
- 名称:输入一个描述性名称(例如
Chronicle HackerOne Webhook API Key)。
- 名称:输入一个描述性名称(例如
- 在 API 限制下:
- 选择限制密钥。
- 在选择 API 列表中,搜索并选择 Google SecOps API(或 Chronicle API)。
- 点击保存。
- 从页面顶部的 API 密钥字段复制 API 密钥值。
安全地保存 API 密钥。
配置 HackerOne webhook
构建网络钩子网址
将 Chronicle 端点网址和 API 密钥组合在一起:
<ENDPOINT_URL>?key=<API_KEY>示例:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
在 HackerOne 中创建 webhook
- 登录 HackerOne,然后前往您的计划。
- 前往互动,点击要配置的计划对应的三点状菜单,然后点击设置。
- 依次前往自动化 > Webhook。
- 点击新建 Webhook。
- 提供以下配置详细信息:
- 载荷网址:粘贴包含 API 密钥的完整端点网址(如上所示)。
- 密钥:粘贴从 Chronicle Feed 创建过程中获得的密钥。
- 选择要触发 Webhook 的事件:选择以下选项之一:
- 向我发送所有内容:所有事件都会触发网络钩子。
- 让我指定个别事件:选择要发送到 Chronicle 的特定事件。用于安全监控的推荐事件:
- report_created:黑客提交新的漏洞报告时
- report_triaged:报告已分诊
- report_resolved:当报告得到解决时
- report_bounty_awarded:赏金发放时
- report_swag_awarded:何时奖励了礼品
- program_hacker_joined:黑客加入计划时
- program_hacker_left:当黑客退出计划时
- 点击 Add webhook。
测试网络钩子
- 在 Webhook 配置页面中,选择测试请求,向配置的载荷网址发送示例请求。
- 验证响应是否为 HTTP 200。
- 在 1 到 2 分钟内检查 Chronicle Feed 中是否显示测试事件。
验证 Webhook 是否正常运行
检查 HackerOne Webhook 状态
- 登录 HackerOne 控制台。
- 前往互动,点击相应计划的 Kebab 菜单,然后点击设置。
- 依次前往自动化 > Webhook。
- 点击相应 Webhook 即可查看详细信息。
- 在最近的传送部分下,验证最近的传送是否显示成功状态 (HTTP 200)。
- 点击任意传送,即可查看 POST 载荷请求。
检查 Chronicle Feed 状态
- 在 Chronicle 中,依次前往 SIEM 设置 > Feed。
- 找到您的 HackerOne 网络钩子 Feed。
- 查看状态列(应为有效)。
- 检查收到的事件数(应会递增)。
- 检查上次成功启动时间时间戳(应为最近的时间)。
验证 Chronicle 中的日志
- 依次前往搜索 > UDM 搜索。
使用以下查询:
metadata.vendor_name = "HACKERONE" AND metadata.product_name = "HACKERONE"将时间范围调整为“过去 1 小时”。
验证活动是否显示在结果中。
身份验证方法参考
Chronicle webhook Feed 支持多种身份验证方法。HackerOne Webhook 结合使用了查询参数和签名验证。
方法 1:使用签名验证的查询参数(建议用于 HackerOne)
HackerOne 会向配置的负载网址发送 webhook。身份验证通过以下方式处理:
- 网址中的 API 密钥:Chronicle API 密钥以查询参数的形式附加到载荷网址。
Secret 签名验证:HackerOne 会生成一个 X-H1-Signature 标头,其中包含使用配置的 Secret 签名的请求正文的 HMAC SHA256 hexdigest。
网址格式:
<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 hexdigest(格式:
sha256=<hexdigest>) - X-H1-Event:触发 Webhook 的事件类型
- X-H1-Delivery:配送的唯一标识符
- X-H1-Signature:请求正文的 HMAC SHA256 hexdigest(格式:
如需验证接收端点上的签名,请执行以下操作:
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)
网络钩子事件类型
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 专业人士的解答。