收集 Fastly WAF 日志
概览
此解析器可从 Fastly WAF JSON 日志中提取字段,对其进行转换和重命名,然后将其映射到 UDM。它可处理各种数据类型、转换严重程度,并根据可用的 IP 和主机名信息对事件进行分类。它还会处理潜在的解析失败并舍弃格式错误的日志条目。
准备工作
确保您满足以下前提条件:
- Google SecOps 实例。
- 有权配置 WAF 设置的 Fastly 账号。
设置 Feed
您可以通过两种不同的入口点在 Google SecOps 平台中设置 Feed:
- SIEM 设置 > Feed
- 内容中心 > 内容包
通过“SIEM 设置”>“Feed”设置 Feed
如需配置 Feed,请按以下步骤操作:
- 依次前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 在下一页上,点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如 Fastly WAF 日志)。
- 选择 Webhook 作为来源类型。
- 选择 Fastly WAF 作为日志类型。
- 点击下一步。
- 可选:为以下输入参数指定值:
- 拆分分隔符:用于分隔日志行的分隔符,例如
\n
。
- 拆分分隔符:用于分隔日志行的分隔符,例如
- 点击下一步。
- 在最终确定界面中检查 Feed 配置,然后点击提交。
- 点击生成密钥,生成用于对此 Feed 进行身份验证的密钥。
- 复制并存储密钥。您将无法再次查看此密钥。如有需要,您可以重新生成新的 Secret 密钥,但此操作会使之前的 Secret 密钥失效。
- 在详情标签页中,从端点信息字段复制 Feed 端点网址。您需要在客户端应用中指定此端点网址。
- 点击完成。
设置来自内容中心的 Feed
为以下字段指定值:
- 拆分分隔符:用于分隔日志行的分隔符,例如
\n
。
高级选项
- Feed 名称:用于标识 Feed 的预填充值。
- 来源类型:用于将日志收集到 Google SecOps 中的方法。
- 资源命名空间:与 Feed 关联的命名空间。
提取标签:应用于相应 Feed 中所有事件的标签。
点击生成密钥,生成用于对此 Feed 进行身份验证的密钥。
复制并存储密钥。您将无法再次查看此密钥。如有需要,您可以重新生成新的 Secret 密钥,但此操作会使之前的 Secret 密钥失效。
在详情标签页中,从端点信息字段复制 Feed 端点网址。您需要在客户端应用中指定此端点网址。
为 Webhook Feed 创建 API 密钥
前往 Google Cloud 控制台 > 凭据。
点击创建凭据,然后选择 API 密钥。
将 API 密钥访问权限限制为 Google Security Operations API。
指定端点网址
- 在客户端应用中,指定 webhook Feed 中提供的 HTTPS 端点网址。
通过在自定义标头中指定 API 密钥和密钥来启用身份验证,格式如下:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET
建议:将 API 密钥指定为标头,而不是在网址中指定。
如果您的 Webhook 客户端不支持自定义标头,您可以使用以下格式的查询参数指定 API 密钥和密钥:
ENDPOINT_URL?key=API_KEY&secret=SECRET
替换以下内容:
ENDPOINT_URL
:Feed 端点网址。API_KEY
:用于向 Google Security Operations 进行身份验证的 API 密钥。SECRET
:您生成的用于验证 Feed 的密钥。
在 Fastly 中配置 webhook
- 登录 Fastly。
- 可选:在网站菜单中选择一个网站(如果您有多个网站)。
- 依次选择管理 > 网站集成。
- 点击添加网站集成。
- 选择 Generic Webhook。
- Webhook 网址:输入 Google SecOps ENDPOINT_网址,然后输入 API_KEY 和 SECRET。
- 提醒放置位置:选择所有活动或特定活动。
- 可选:如果您选择了特定活动,请前往活动菜单,然后选择您希望 Webhook 发送的活动类型。
- 点击创建网站集成。
UDM 映射表
日志字段 | UDM 映射 | 逻辑 |
---|---|---|
anomaly_score |
security_result.detection_fields[].key : "anomaly"security_result.detection_fields[].value : anomaly_score |
如果 waf.score.anomaly 为 0 或空,且 anomaly_score 不为空或不为 0,则使用 anomaly_score 值填充 security_result.detection_fields 数组,键为“anomaly”,值为 anomaly_score 字段。 |
cache_status |
additional.fields[].key : "cache_status"additional.fields[].value.string_value : cache_status |
cache_status 值用于填充 additional.fields 数组,该数组的键为“cache_status”,值为 cache_status 字段。 |
client_ip |
principal.ip :client_ip |
client_ip 字段已映射到 principal.ip 。 |
connection.fastly_is_edge |
additional.fields[].key : "fastly_is_edge"additional.fields[].value.bool_value : connection.fastly_is_edge |
connection.fastly_is_edge 值用于填充 additional.fields 数组,该数组的键为“fastly_is_edge”,值为 connection.fastly_is_edge 字段的值。 |
connection.fastly_is_shield |
additional.fields[].key : "fastly_is_shield"additional.fields[].value.bool_value : connection.fastly_is_shield |
connection.fastly_is_shield 值用于填充 additional.fields 数组,该数组的键为“fastly_is_shield”,值为 connection.fastly_is_shield 字段的值。 |
connection.request_tls_version |
network.tls.version :connection.request_tls_version |
connection.request_tls_version 字段已映射到 network.tls.version 。 |
fastly.server |
target.hostname :fastly.server |
fastly.server 字段已映射到 target.hostname 。 |
fastly.service_id |
additional.fields[].key : "service_id"additional.fields[].value.string_value : fastly.service_id |
fastly.service_id 值用于填充 additional.fields 数组,该数组的键为“service_id”,值为 fastly.service_id 字段。 |
geo.city |
principal.location.city :geo.city |
geo.city 字段已映射到 principal.location.city 。 |
geo.country |
principal.location.country_or_region :geo.country |
geo.country 字段已映射到 principal.location.country_or_region 。 |
geo.location |
principal.location.region_latitude :从 geo.location 中提取principal.location.region_longitude :从 geo.location 中提取 |
使用正则表达式从 geo.location 字段中提取经度和纬度,并分别映射到 principal.location.region_latitude 和 principal.location.region_longitude 。 |
geo.region |
principal.location.state :geo.region |
geo.region 字段已映射到 principal.location.state 。 |
host |
principal.hostname :host |
host 字段已映射到 principal.hostname 。 |
request_headers.accept_charset |
additional.fields[].key : "accept_charset"additional.fields[].value.string_value : request_headers.accept_charset |
request_headers.accept_charset 值用于填充 additional.fields 数组,该数组的键为“accept_charset”,值为 request_headers.accept_charset 字段。 |
request_headers.accept_language |
additional.fields[].key : "accept_language"additional.fields[].value.string_value : request_headers.accept_language |
request_headers.accept_language 值用于填充 additional.fields 数组,该数组的键为“accept_language”,值为 request_headers.accept_language 字段的值。 |
request_headers.referer |
network.http.referral_url :request_headers.referer |
request_headers.referer 字段已映射到 network.http.referral_url 。 |
request_headers.user_agent |
network.http.user_agent :request_headers.user_agent |
request_headers.user_agent 字段已映射到 network.http.user_agent 。 |
request_id |
metadata.product_log_id :request_id |
request_id 字段已映射到 metadata.product_log_id 。 |
request_method |
network.http.method :request_method |
request_method 字段已映射到 network.http.method 。 |
response_headers.cache_control |
additional.fields[].key : "cache_control"additional.fields[].value.string_value : response_headers.cache_control |
response_headers.cache_control 值用于填充 additional.fields 数组,该数组的键为“cache_control”,值为 response_headers.cache_control 字段。 |
response_headers.content_type |
additional.fields[].key : "content_type"additional.fields[].value.string_value : response_headers.content_type |
response_headers.content_type 值用于填充 additional.fields 数组,该数组的键为“content_type”,值为 response_headers.content_type 字段。 |
response_state |
additional.fields[].key : "response_state"additional.fields[].value.string_value : response_state |
response_state 值用于填充 additional.fields 数组,该数组的键为“response_state”,值为 response_state 字段的值。 |
response_status |
network.http.response_code :response_status |
如果 status 字段为空,则 response_status 字段会映射到 network.http.response_code 。 |
rule_id |
security_result.rule_id :rule_id |
如果 waf.rule_id 为空,则使用 rule_id 值填充 security_result.rule_id 。 |
severity |
waf.severity :severity |
severity 字段值会复制到 waf.severity 。 |
size_bytes.request_header |
network.sent_bytes :size_bytes.request_header |
size_bytes.request_header 字段已映射到 network.sent_bytes 。 |
size_bytes.response_header |
network.received_bytes :size_bytes.response_header |
size_bytes.response_header 字段已映射到 network.received_bytes 。 |
status |
network.http.response_code :status |
status 字段已映射到 network.http.response_code 。 |
timestamp |
metadata.event_timestamp :timestamp |
系统会解析 timestamp 字段并将其映射到 metadata.event_timestamp 。 |
url |
target.url :url |
url 字段已映射到 target.url 。 |
waf.blocked |
security_result.action :派生 |
如果 waf.blocked 为 false,则将 security_result.action 设置为“ALLOW”。如果 waf.blocked 为 true,则将 security_result.action 设置为“BLOCK”。 |
waf.executed |
security_result.detection_fields[].key : "executed"security_result.detection_fields[].value : waf.executed |
waf.executed 值用于填充 security_result.detection_fields 数组,其中包含一个键“executed”和 waf.executed 字段的值。 |
waf.failures |
security_result.detection_fields[].key : "failures"security_result.detection_fields[].value : waf.failures |
waf.failures 值用于填充 security_result.detection_fields 数组,该数组包含一个键“failures”和 waf.failures 字段的值。 |
waf.logged |
security_result.detection_fields[].key : "logged"security_result.detection_fields[].value : waf.logged |
waf.logged 值用于填充 security_result.detection_fields 数组,该数组的键为“logged”,值为 waf.logged 字段。 |
waf.message |
metadata.description :waf.message |
如果 waf.message 不为空,则会映射到 metadata.description 。 |
waf.rule_id |
security_result.rule_id :waf.rule_id |
如果 waf.rule_id 不为空,则会映射到 security_result.rule_id 。 |
waf.score.anomaly |
security_result.detection_fields[].key : "anomaly"security_result.detection_fields[].value : waf.score.anomaly |
如果 waf.score.anomaly 不为 0 且不为空,则该值用于填充 security_result.detection_fields 数组,其中键为“anomaly”,值为 waf.score.anomaly 字段。 |
waf.score.http_violation |
security_result.detection_fields[].key : "http_violation"security_result.detection_fields[].value : waf.score.http_violation |
如果 waf.score.http_violation 不为 0 且不为空,则该值用于填充 security_result.detection_fields 数组。 |
waf.score.lfi |
security_result.detection_fields[].key : "lfi"security_result.detection_fields[].value : waf.score.lfi |
与 waf.score.http_violation 类似的逻辑。 |
waf.score.php_injection |
security_result.detection_fields[].key : "php_injection"security_result.detection_fields[].value : waf.score.php_injection |
与 waf.score.http_violation 类似的逻辑。 |
waf.score.rce |
security_result.detection_fields[].key : "rce"security_result.detection_fields[].value : waf.score.rce |
与 waf.score.http_violation 类似的逻辑。 |
waf.score.rfi |
security_result.detection_fields[].key : "rfi"security_result.detection_fields[].value : waf.score.rfi |
与 waf.score.http_violation 类似的逻辑。 |
waf.score.session_fixation |
security_result.detection_fields[].key : "session_fixation"security_result.detection_fields[].value : waf.score.session_fixation |
与 waf.score.http_violation 类似的逻辑。 |
waf.score.sql_injection |
security_result.detection_fields[].key : "sql_injection"security_result.detection_fields[].value : waf.score.sql_injection |
与 waf.score.http_violation 类似的逻辑。 |
waf.score.xss |
security_result.detection_fields[].key : "xss"security_result.detection_fields[].value : waf.score.xss |
与 waf.score.http_violation 类似的逻辑。 |
waf.severity |
security_result.severity :派生security_result.severity_details :waf.severity |
如果 waf.severity 不为空,则根据范围确定 security_result.severity 的值(<=3:HIGH,>3 且 <=6:MEDIUM,>6 且 <=8:LOW,否则:UNKNOWN_SEVERITY)。原始 waf.severity 值也会映射到 security_result.severity_details 。 |
waf_message |
metadata.description :waf_message |
如果 waf.message 为空,但 waf_message 不为空,则会映射到 metadata.description 。如果 client_ip 或 host 和 fastly.server 不为空,则将 metadata.event_type 设置为“NETWORK_HTTP”。否则,如果 client_ip 或 host 不为空,则将 metadata.event_type 设置为“STATUS_UPDATE”。否则,该值会设置为“GENERIC_EVENT”。硬编码的值。硬编码的值。硬编码的值。 |
需要更多帮助?从社区成员和 Google SecOps 专业人士那里获得解答。