收集 HackerOne 日志

支持的平台:

本文档介绍了如何配置 HackerOne 以使用 Webhook 将日志推送到 Google Security Operations。

HackerOne 是一个漏洞协调和 bug 赏金平台,可将组织与安全研究人员联系起来,以识别和修复安全漏洞。该平台提供 bug 赏金计划、漏洞披露计划、渗透测试以及贯穿整个软件开发生命周期的持续安全测试。

准备工作

确保您满足以下前提条件:

  • Google SecOps 实例
  • 采用专业版或企业版层级的 HackerOne 计划(Webhook 仅适用于这些层级)
  • 对 HackerOne 计划设置的管理员访问权限

在 Google SecOps 中创建 Webhook Feed

创建 Feed

  1. 依次前往 SIEM 设置 > Feed
  2. 点击添加新 Feed
  3. 在下一页上,点击配置单个 Feed
  4. Feed 名称字段中,输入 Feed 的名称(例如 HackerOne Vulnerability Reports)。
  5. 选择 Webhook 作为来源类型
  6. 选择 HackerOne 作为日志类型
  7. 点击下一步
  8. 为以下输入参数指定值:
    • 拆分分隔符(可选):留空。每个 webhook 请求都包含一个 JSON 事件。
    • 资产命名空间资产命名空间
    • 注入标签:要应用于此 Feed 中事件的标签。
  9. 点击下一步
  10. 最终确定界面中查看新的 Feed 配置,然后点击提交

生成并保存密钥

创建 Feed 后,您必须生成用于身份验证的密钥:

  1. 在 Feed 详情页面上,点击生成密钥
  2. 系统会显示一个包含密钥的对话框。
  3. 复制并妥善保存此密钥。

获取 Feed 端点网址

  1. 前往 Feed 的详细信息标签页。
  2. 端点信息部分,复制 Feed 端点网址
  3. 网址格式为:

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

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  4. 保存此网址以供后续步骤使用。

  5. 点击完成

创建 Google Cloud API 密钥

Chronicle 需要 API 密钥才能进行身份验证。在 Google Cloud Console 中创建受限 API 密钥。

创建 API 密钥

  1. 前往 Google Cloud 控制台的“凭据”页面
  2. 选择您的项目(与您的 Chronicle 实例关联的项目)。
  3. 依次点击创建凭据> API 密钥
  4. 系统会创建一个 API 密钥,并在对话框中显示该密钥。
  5. 点击修改 API 密钥以限制密钥。

限制 API 密钥

  1. API 密钥设置页面中:
    • 名称:输入一个描述性名称(例如 Chronicle HackerOne Webhook API Key)。
  2. API 限制下:
    1. 选择限制密钥
    2. 选择 API 列表中,搜索并选择 Google SecOps API(或 Chronicle API)。
  3. 点击保存
  4. 从页面顶部的 API 密钥字段复制 API 密钥值。
  5. 安全地保存 API 密钥。

配置 HackerOne webhook

构建网络钩子网址

  • 将 Chronicle 端点网址和 API 密钥组合在一起:

    <ENDPOINT_URL>?key=<API_KEY>
    
    • 示例

      https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
      

在 HackerOne 中创建 webhook

  1. 登录 HackerOne,然后前往您的计划。
  2. 前往互动,点击要配置的计划对应的三点状菜单,然后点击设置
  3. 依次前往自动化 > Webhook
  4. 点击新建 Webhook
  5. 提供以下配置详细信息:
    • 载荷网址:粘贴包含 API 密钥的完整端点网址(如上所示)。
    • 密钥:粘贴从 Chronicle Feed 创建过程中获得的密钥。
    • 选择要触发 Webhook 的事件:选择以下选项之一:
      • 向我发送所有内容:所有事件都会触发网络钩子。
      • 让我指定个别事件:选择要发送到 Chronicle 的特定事件。用于安全监控的推荐事件:
        • report_created:黑客提交新的漏洞报告时
        • report_triaged:报告已分诊
        • report_resolved:当报告得到解决时
        • report_bounty_awarded:赏金发放时
        • report_swag_awarded:何时奖励了礼品
        • program_hacker_joined:黑客加入计划时
        • program_hacker_left:当黑客退出计划时
  6. 点击 Add webhook

测试网络钩子

  1. 在 Webhook 配置页面中,选择测试请求,向配置的载荷网址发送示例请求。
  2. 验证响应是否为 HTTP 200。
  3. 在 1 到 2 分钟内检查 Chronicle Feed 中是否显示测试事件。

验证 Webhook 是否正常运行

检查 HackerOne Webhook 状态

  1. 登录 HackerOne 控制台。
  2. 前往互动,点击相应计划的 Kebab 菜单,然后点击设置
  3. 依次前往自动化 > Webhook
  4. 点击相应 Webhook 即可查看详细信息。
  5. 最近的传送部分下,验证最近的传送是否显示成功状态 (HTTP 200)。
  6. 点击任意传送,即可查看 POST 载荷请求。

检查 Chronicle Feed 状态

  1. 在 Chronicle 中,依次前往 SIEM 设置 > Feed
  2. 找到您的 HackerOne 网络钩子 Feed。
  3. 查看状态列(应为有效)。
  4. 检查收到的事件数(应会递增)。
  5. 检查上次成功启动时间时间戳(应为最近的时间)。

验证 Chronicle 中的日志

  1. 依次前往搜索 > UDM 搜索
  2. 使用以下查询:

    metadata.vendor_name = "HACKERONE" AND metadata.product_name = "HACKERONE"
    
  3. 将时间范围调整为“过去 1 小时”。

  4. 验证活动是否显示在结果中。

身份验证方法参考

Chronicle webhook Feed 支持多种身份验证方法。HackerOne Webhook 结合使用了查询参数和签名验证。

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:配送的唯一标识符
  • 如需验证接收端点上的签名,请执行以下操作:

    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 专业人士的解答。