Collecter les journaux du WAF Fastly

Compatible avec:

Présentation

Cet analyseur extrait des champs des journaux JSON du WAF Fastly, les transforme et les renomme, puis les met en correspondance avec l'UDM. Il gère différents types de données, convertit les niveaux de gravité et catégorise les événements en fonction des informations d'adresse IP et de nom d'hôte disponibles. Il gère également les échecs d'analyse potentiels et supprime les entrées de journal mal formées.

Avant de commencer

  • Assurez-vous de disposer d'une instance Google SecOps.
  • Un compte Fastly avec accès à la configuration des paramètres du WAF

Configurer un flux dans Google SecOps pour ingérer les journaux du WAF Fastly

  1. Accédez à Paramètres du SIEM > Flux.
  2. Cliquez sur Ajouter.
  3. Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple, Journaux du WAF Fastly).
  4. Sélectionnez Webhook comme type de source.
  5. Sélectionnez Fastly WAF comme type de journal.
  6. Cliquez sur Suivant.
  7. Facultatif: spécifiez des valeurs pour les paramètres d'entrée suivants :
    • Délimiteur de fractionnement: délimiteur utilisé pour séparer les lignes de journal, par exemple \n.
    • Espace de noms des éléments: espace de noms des éléments.
    • Libellés d'ingestion: libellé appliqué aux événements de ce flux.
  8. Cliquez sur Suivant.
  9. Vérifiez la configuration du flux dans l'écran Finaliser, puis cliquez sur Envoyer.
  10. Cliquez sur Générer une clé secrète pour générer une clé secrète permettant d'authentifier ce flux.
  11. Copiez et stockez la clé secrète. Vous ne pourrez plus afficher cette clé secrète. Si nécessaire, vous pouvez générer une nouvelle clé secrète, mais cette action rend l'ancienne clé secrète obsolète.
  12. Dans l'onglet Détails, copiez l'URL du point de terminaison du flux dans le champ Informations sur le point de terminaison. Vous devez spécifier cette URL de point de terminaison dans votre application cliente.
  13. Cliquez sur OK.

Créer une clé API pour le flux webhook

  1. Accédez à la console Google Cloud > Identifiants.

    Accéder à "Identifiants"

  2. Cliquez sur Créer des identifiants, puis sélectionnez Clé API.

  3. Limitez l'accès de la clé API à l'API Google Security Operations.

Spécifier l'URL du point de terminaison

  1. Dans votre application cliente, spécifiez l'URL du point de terminaison HTTPS fournie dans le flux de webhook.
  2. Activez l'authentification en spécifiant la clé API et la clé secrète dans l'en-tête personnalisé au format suivant:

    X-goog-api-key = API_KEY
    X-Webhook-Access-Key = SECRET
    

    Recommandation: Spécifiez la clé API en tant qu'en-tête plutôt que dans l'URL.

  3. Si votre client webhook n'est pas compatible avec les en-têtes personnalisés, vous pouvez spécifier la clé API et la clé secrète à l'aide de paramètres de requête au format suivant:

    ENDPOINT_URL?key=API_KEY&secret=SECRET
    

    Remplacez les éléments suivants :

    • ENDPOINT_URL: URL du point de terminaison du flux.
    • API_KEY: clé API permettant de s'authentifier auprès de Google Security Operations.
    • SECRET: clé secrète que vous avez générée pour authentifier le flux.

Configurer le webhook dans Fastly

  1. Connectez-vous à Fastly.
  2. (Facultatif) Sélectionnez un site dans le menu Sites (si vous possédez plusieurs sites).
  3. Sélectionnez Gérer > Intégrations de sites.
  4. Cliquez sur Ajouter une intégration de site.
  5. Sélectionnez Webhook générique.
  6. URL du webhook: saisissez l'ENDPOINT_URL Google SecOps, suivi de API_KEY et de SECRET.
  7. Emplacement de l'alerte: sélectionnez Toute activité ou Activité spécifique.
  8. Facultatif: Si vous avez sélectionné Activité spécifique, accédez au menu Activité et sélectionnez les types d'activités que vous souhaitez que le webhook envoie.
  9. Cliquez sur Créer une intégration de site.

Tableau de mappage UDM

Champ de journal Mappage UDM Logique
anomaly_score security_result.detection_fields[].key: "anomaly"
security_result.detection_fields[].value: anomaly_score
Si waf.score.anomaly est égal à 0 ou vide, et que anomaly_score n'est pas vide ni égal à 0, la valeur anomaly_score est utilisée pour renseigner le tableau security_result.detection_fields avec une clé "anomaly" (anomalie) et la valeur du champ anomaly_score.
cache_status additional.fields[].key: "cache_status"
additional.fields[].value.string_value: cache_status
La valeur cache_status permet de renseigner le tableau additional.fields avec une clé "cache_status" et la valeur du champ cache_status.
client_ip principal.ip : client_ip Le champ client_ip est mappé sur principal.ip.
connection.fastly_is_edge additional.fields[].key: "fastly_is_edge"
additional.fields[].value.bool_value: connection.fastly_is_edge
La valeur connection.fastly_is_edge permet de renseigner le tableau additional.fields avec une clé "fastly_is_edge" et la valeur du champ connection.fastly_is_edge.
connection.fastly_is_shield additional.fields[].key: "fastly_is_shield"
additional.fields[].value.bool_value: connection.fastly_is_shield
La valeur connection.fastly_is_shield permet de renseigner le tableau additional.fields avec une clé "fastly_is_shield" et la valeur du champ connection.fastly_is_shield.
connection.request_tls_version network.tls.version : connection.request_tls_version Le champ connection.request_tls_version est mappé sur network.tls.version.
fastly.server target.hostname : fastly.server Le champ fastly.server est mappé sur target.hostname.
fastly.service_id additional.fields[].key: "service_id"
additional.fields[].value.string_value: fastly.service_id
La valeur fastly.service_id permet de renseigner le tableau additional.fields avec une clé "service_id" et la valeur du champ fastly.service_id.
geo.city principal.location.city : geo.city Le champ geo.city est mappé sur principal.location.city.
geo.country principal.location.country_or_region : geo.country Le champ geo.country est mappé sur principal.location.country_or_region.
geo.location principal.location.region_latitude: extrait de geo.location
principal.location.region_longitude: extrait de geo.location
La latitude et la longitude sont extraites du champ geo.location à l'aide d'une expression régulière et mappées sur principal.location.region_latitude et principal.location.region_longitude, respectivement.
geo.region principal.location.state : geo.region Le champ geo.region est mappé sur principal.location.state.
host principal.hostname : host Le champ host est mappé sur principal.hostname.
request_headers.accept_charset additional.fields[].key: "accept_charset"
additional.fields[].value.string_value: request_headers.accept_charset
La valeur request_headers.accept_charset permet de renseigner le tableau additional.fields avec une clé "accept_charset" et la valeur du champ request_headers.accept_charset.
request_headers.accept_language additional.fields[].key: "accept_language"
additional.fields[].value.string_value: request_headers.accept_language
La valeur request_headers.accept_language permet de renseigner le tableau additional.fields avec une clé "accept_language" et la valeur du champ request_headers.accept_language.
request_headers.referer network.http.referral_url : request_headers.referer Le champ request_headers.referer est mappé sur network.http.referral_url.
request_headers.user_agent network.http.user_agent : request_headers.user_agent Le champ request_headers.user_agent est mappé sur network.http.user_agent.
request_id metadata.product_log_id : request_id Le champ request_id est mappé sur metadata.product_log_id.
request_method network.http.method : request_method Le champ request_method est mappé sur network.http.method.
response_headers.cache_control additional.fields[].key: "cache_control"
additional.fields[].value.string_value: response_headers.cache_control
La valeur response_headers.cache_control permet de renseigner le tableau additional.fields avec une clé "cache_control" et la valeur du champ response_headers.cache_control.
response_headers.content_type additional.fields[].key: "content_type"
additional.fields[].value.string_value: response_headers.content_type
La valeur response_headers.content_type permet de renseigner le tableau additional.fields avec une clé "content_type" et la valeur du champ response_headers.content_type.
response_state additional.fields[].key: "response_state"
additional.fields[].value.string_value: response_state
La valeur response_state permet de renseigner le tableau additional.fields avec une clé "response_state" et la valeur du champ response_state.
response_status network.http.response_code : response_status Le champ response_status est mappé sur network.http.response_code si le champ status est vide.
rule_id security_result.rule_id : rule_id Si waf.rule_id est vide, la valeur rule_id est utilisée pour renseigner security_result.rule_id.
severity waf.severity : severity La valeur du champ severity est copiée dans waf.severity.
size_bytes.request_header network.sent_bytes : size_bytes.request_header Le champ size_bytes.request_header est mappé sur network.sent_bytes.
size_bytes.response_header network.received_bytes : size_bytes.response_header Le champ size_bytes.response_header est mappé sur network.received_bytes.
status network.http.response_code : status Le champ status est mappé sur network.http.response_code.
timestamp metadata.event_timestamp : timestamp Le champ timestamp est analysé et mappé sur metadata.event_timestamp.
url target.url : url Le champ url est mappé sur target.url.
waf.blocked security_result.action: dérivé Si waf.blocked est défini sur "false", security_result.action est défini sur "ALLOW". Si waf.blocked est défini sur "true", security_result.action est défini sur "BLOCK".
waf.executed security_result.detection_fields[].key: "executed"
security_result.detection_fields[].value: waf.executed
La valeur waf.executed permet de renseigner le tableau security_result.detection_fields avec une clé "executed" et la valeur du champ waf.executed.
waf.failures security_result.detection_fields[].key: "failures"
security_result.detection_fields[].value: waf.failures
La valeur waf.failures permet de renseigner le tableau security_result.detection_fields avec une clé "failures" et la valeur du champ waf.failures.
waf.logged security_result.detection_fields[].key: "logged"
security_result.detection_fields[].value: waf.logged
La valeur waf.logged permet de renseigner le tableau security_result.detection_fields avec une clé "logged" et la valeur du champ waf.logged.
waf.message metadata.description : waf.message Si waf.message n'est pas vide, il est mappé sur metadata.description.
waf.rule_id security_result.rule_id : waf.rule_id Si waf.rule_id n'est pas vide, il est mappé sur security_result.rule_id.
waf.score.anomaly security_result.detection_fields[].key: "anomaly"
security_result.detection_fields[].value: waf.score.anomaly
Si waf.score.anomaly n'est pas égal à 0 et n'est pas vide, la valeur est utilisée pour renseigner le tableau security_result.detection_fields avec une clé "anomaly" et la valeur du champ waf.score.anomaly.
waf.score.http_violation security_result.detection_fields[].key: "http_violation"
security_result.detection_fields[].value: waf.score.http_violation
Si waf.score.http_violation n'est pas égal à 0 et n'est pas vide, la valeur est utilisée pour renseigner le tableau security_result.detection_fields.
waf.score.lfi security_result.detection_fields[].key: "lfi"
security_result.detection_fields[].value: waf.score.lfi
Logique similaire à waf.score.http_violation.
waf.score.php_injection security_result.detection_fields[].key: "php_injection"
security_result.detection_fields[].value: waf.score.php_injection
Logique similaire à waf.score.http_violation.
waf.score.rce security_result.detection_fields[].key: "rce"
security_result.detection_fields[].value: waf.score.rce
Logique similaire à celle de waf.score.http_violation.
waf.score.rfi security_result.detection_fields[].key: "rfi"
security_result.detection_fields[].value: waf.score.rfi
Logique similaire à celle de waf.score.http_violation.
waf.score.session_fixation security_result.detection_fields[].key: "session_fixation"
security_result.detection_fields[].value: waf.score.session_fixation
Logique similaire à celle de waf.score.http_violation.
waf.score.sql_injection security_result.detection_fields[].key: "sql_injection"
security_result.detection_fields[].value: waf.score.sql_injection
Logique similaire à celle de waf.score.http_violation.
waf.score.xss security_result.detection_fields[].key: "xss"
security_result.detection_fields[].value: waf.score.xss
Logique similaire à celle de waf.score.http_violation.
waf.severity security_result.severity: derived
security_result.severity_details: waf.severity
Si waf.severity n'est pas vide, il détermine la valeur de security_result.severity en fonction des plages (<=3: ÉLEVÉ, >3 et <=6: MOYEN, >6 et <=8: BAS, sinon: UNKNOWN_SEVERITY). La valeur waf.severity d'origine est également mappée sur security_result.severity_details.
waf_message metadata.description : waf_message Si waf.message est vide et que waf_message ne l'est pas, il est mappé sur metadata.description. Si client_ip ou host et fastly.server ne sont pas vides, metadata.event_type est défini sur "NETWORK_HTTP". Sinon, si client_ip ou host ne sont pas vides, metadata.event_type est défini sur "STATUS_UPDATE". Sinon, il est défini sur "GENERIC_EVENT". Valeur codée en dur. Valeur codée en dur. Valeur codée en dur.

Modifications

2022-06-06

  • Analyseur nouvellement créé.