收集 HackerOne 日志
本文档介绍了如何配置 HackerOne 以使用 Webhook 将日志推送到 Google Security Operations。
HackerOne 是一个漏洞协调和 bug 赏金平台,可将组织与安全研究人员联系起来,以识别和修复安全漏洞。该平台提供 bug 赏金计划、漏洞披露计划、渗透测试以及整个软件开发生命周期的持续安全测试。
准备工作
确保您满足以下前提条件:
Google SecOps 实例
HackerOne 计划,且为专业版或企业版(Webhook 仅适用于这些版本)
具备对 HackerOne 计划设置的管理员权限
有权访问 Google Cloud Console(用于创建 API 密钥)
在 Google SecOps 中创建 Webhook Feed
创建 Feed
- 依次前往 SIEM 设置 > Feed。
- 点击添加新 Feed 。
- 在下一页上,点击配置单个 Feed 。
- 在 Feed 名称 字段中,输入 Feed 的名称(例如
HackerOne Webhook)。 - 选择 Webhook 作为来源类型 。
- 选择 HackerOne 作为日志类型 。
- 点击下一步 。
- 为以下输入参数指定值:
- 拆分分隔符:留空。每个 Webhook 请求都包含一个 JSON 事件。
- 资产命名空间:资产命名空间
- 提取标签:要应用于此 Feed 中事件的标签
- 点击下一步 。
- 在最终确定 屏幕中查看新的新闻信息流配置,然后点击提交 。
生成并保存密钥
创建 Feed 后,您必须生成密钥以进行身份验证:
- 在 Feed 详情页面上,点击生成密钥 。
- 对话框会显示密钥。
- 复制并妥善保存 密钥。
重要提示:密钥只会显示一次,之后无法检索。如果丢失,您必须生成新密钥。
获取 Feed 端点网址
- 前往 Feed 的详情 标签页。
- 在端点信息 部分中,复制 Feed 端点网址 。
网址格式为:
https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import其中,
{region}是 Google SecOps 实例的区域(例如us、europe或asia-southeast1),{parent}是资源路径,格式为projects/<PROJECT_ID>/locations/<LOCATION>/instances/<INSTANCE_ID>/logTypes/<LOG_TYPE>。保存此网址,以在后续步骤中使用。
点击完成 。
创建 Google Cloud API 密钥
Chronicle 需要 API 密钥进行身份验证。在 Google Cloud Console 中创建受限 API 密钥。
创建 API 密钥
- 前往 Google Cloud 控制台的“凭据”页面。
- 选择您的项目(与您的 Google SecOps 实例关联的项目)。
- 点击创建凭据 > API 密钥。
- 系统会创建 API 密钥,并在对话框中显示。
- 点击修改 API 密钥 以限制密钥。
限制 API 密钥
- 在 API 密钥 设置页面中:
- 名称:输入一个描述性名称(例如
Chronicle HackerOne Webhook API Key)。
- 名称:输入一个描述性名称(例如
- 在 API 限制 下:
- 选择限制密钥 。
- 在选择 API 下拉菜单中,搜索并选择 Google SecOps API (或 Chronicle API )。
- 点击保存 。
- 从页面顶部的 API 密钥 字段中复制 API 密钥值。
妥善保存 API 密钥。
配置 HackerOne Webhook
构建网络钩子网址
将 Google SecOps 端点网址、API 密钥和密钥合并为一个网址。API 密钥和密钥都必须作为查询参数附加。
网址格式:
```none
<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>
```
示例:
```none
https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import?key=AIzaSyD...&secret=abcd1234...
```
替换以下内容:
- <ENDPOINT_URL>:获取 Feed 端点网址 部分中的 Feed 端点网址。
- <API_KEY>:创建 Google Cloud API 密钥 部分中的 Google Cloud API 密钥。
- <SECRET_KEY>: **生成并保存密钥** 部分中的密钥。
重要提示:请勿将 Google SecOps 密钥放入 HackerOne 的 Secret 字段中。HackerOne Secret 字段用于 HMAC 载荷签名验证(X-H1-Signature 标头),这与 Google SecOps Webhook 身份验证是不同的机制。将 Google SecOps 密钥放入 HackerOne 的 Secret 字段中会导致 403 Forbidden 错误,因为 HackerOne 不会将该值作为 Google SecOps 身份验证凭据传递。请改为在 Payload URL 中将 key 和 secret 作为查询参数附加。
在 HackerOne 中创建 Webhook
- 登录 HackerOne,然后前往您的计划。
- 前往 Engagements ,点击要配置的计划的纵向排列的三个点状菜单,然后点击 Settings 。
- 前往 Automation > Webhooks。
- 点击新建 Webhook 。
- 提供以下配置详细信息:
- Payload URL:粘贴包含 API 密钥和密钥的完整网址(如上所示)。例如,
https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import?key=AIzaSyD...&secret=abcd1234...。 - Secret:将此字段留空。
- Payload URL:粘贴包含 API 密钥和密钥的完整网址(如上所示)。例如,
- 选择要触发 Webhook 的事件。选择以下选项之一:
- Send me everything:所有事件都会触发 Webhook。
- Let me specify individual events:选择要发送到 Google SecOps 的特定事件。
点击添加 Webhook 。
测试 Webhook
- 在 Webhook 配置页面中,点击测试请求 以向配置的 Payload URL 发送示例请求。
- 验证响应是否为 HTTP 200 。
- 点击您的 Webhook 以查看详细信息。
- 在最近的传送 部分下,验证最近的传送是否显示成功状态 (HTTP 200)。
- 点击任意传送即可查看 POST 载荷请求。
如果您收到错误:
- HTTP 403:验证 API 密钥和密钥是否正确附加为 Payload URL 中的查询参数。确认 HackerOne Secret 字段为空。
- HTTP 401:验证 API 密钥是否有效且仅限于 Google SecOps API。
- HTTP 404:验证端点网址是否正确,并且是否包含完整路径 (/v1/{parent}/logs:import)。
在 Google SecOps 中验证提取
- 在 Google SecOps 中,依次前往 SIEM 设置 > Feed 。
- 找到您的 HackerOne Webhook Feed。
- 查看状态 列(应为有效 )。
- 查看收到的事件 计数(应递增)。
- 查看上次成功时间 时间戳(应为最近的时间戳)。
Webhook 限制和最佳实践
请求限制
| Limit | Value |
|-------|-------|
| **Max request size** | 4 MB |
| **Max QPS (queries per second)** | 15,000 |
| **Request timeout** | 30 seconds |
| **Retry behavior** | Automatic with exponential backoff |
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 | 直接复制值 |