Quelles sont les options dont je dispose pour analyser les journaux AWS WAF stockés dans CloudWatch ou Amazon S3 ?

Dernière mise à jour : 11/07/2022

Je stocke mes journaux AWS WAF dans Amazon CloudWatch, Amazon Simple Storage Solution (Amazon S3) ou Amazon S3 en tant que destination de mon flux de diffusion Amazon Kinesis Data Firehose. Quelles sont les options dont je dispose pour analyser mes journaux d'accès AWS WAF ?

Solution

Pour analyser et filtrer des demandes de journaux spécifiques, utilisez les Amazon CloudWatch Logs Insights pour les journaux CloudWatch ou Amazon Athena pour les journaux Amazon S3.

Analyse des journaux d'accès AWS WAF à l'aide de CloudWatch Logs Insights

  1. Ouvrez la console Amazon CloudWatch.
  2. Dans le panneau de navigation, choisissez Logs (Journaux), puis Log Insights.
  3. Dans Select log group (s) (Sélectionner des groupes de journaux), choisissez un ou plusieurs groupes de journaux à interroger qui incluent des journaux d'accès AWS WAF.
  4. (Facultatif) Choisissez une période d'interrogation.
  5. Utilisez la syntaxe des requêtes pour concevoir des requêtes.
  6. Choisissez Run (Exécuter) pour afficher les résultats du groupe de journaux.

Voici des exemples de requêtes que vous pouvez utiliser pour filtrer des informations spécifiques pour CloudWatch Logs Insights :

Filtrer par chaîne spécifique

Exécutez cette requête pour filtrer le journal en fonction d'une chaîne spécifique :
Remarque : remplacez la chaîne {jndi:ldap. par la chaîne que vous souhaitez rechercher.

fields terminatingRuleId as Rule, action, httpRequest.country as Country, httpRequest.clientIp as ClientIP, httpRequest.httpMethod as Method,httpRequest.uri as URI
| parse @message /\{"name":"[Hh]ost\",\"value":\"(?<Host>[^"}]*)/
| parse @message /\{"name":"[Uu]ser\-[Aa]gent\",\"value\"\:\"(?<UserAgent>[^"}]*)/
| filter @message like "{jndi:ldap"
| sort action, URI desc

Filtrer par hôte

Exécutez cette requête pour filtrer par hôte :
Remarque : remplacez la valeur d'hôte www.example.com par l'hôte que vous souhaitez rechercher.

parse @message /\{"name":"[Hh]ost\",\"value":\"(?<Host>[^"}]*)/
| filter Host = "www.example.com"
| fields terminatingRuleId as Rule, action, httpRequest.country as Country, httpRequest.clientIp as ClientIP, httpRequest.uri as URI

Filtrer par demande POST

Exécutez cette requête pour isoler toutes les demandes POST :

parse @message /\{"name":"[Uu]ser\-[Aa]gent\",\"value\"\:\"(?<UserAgent>[^"}]*)/
| parse @message /\{"name":"[Hh]ost\",\"value":\"(?<Host>[^"}]*)/
| fields terminatingRuleId as Rule, action, httpRequest.country as Country, httpRequest.clientIp as ClientIP, httpRequest.httpMethod as Method, httpRequest.uri as URI, httpRequest.requestId as RequestID
| filter httpRequest.httpMethod ="POST"
| display Rule, action, Country, ClientIP, Method, URI, Host, UserAgent, RequestID
| sort Rule, action desc

Filtrer par UserAgent

Exécutez cette requête pour filtrer par UserAgent :
Remarque : remplacez User-Agent-Value par votre valeur UserAgent.

parse @message /\{"name":"[Uu]ser\-[Aa]gent\",\"value\"\:\"(?<UserAgent>[^"}]*)/
| filter UserAgent like "<User-Agent-Value>"
| fields terminatingRuleId as Rule, action, httpRequest.country as Country, httpRequest.clientIp as ClientIP, httpRequest.uri as URI

Filtrer les demandes ne provenant pas d'un pays

Exécutez cette requête pour filtrer les demandes qui ne proviennent pas d'un pays spécifique :

fields terminatingRuleId as Rule, action, httpRequest.country as Country, httpRequest.clientIp as ClientIP, httpRequest.uri as URI
| parse @message /\{"name":"[Hh]ost\",\"value":\"(?<Host>[^"}]*)/
| parse @message /\{"name":"[Uu]ser\-[Aa]gent\",\"value\"\:\"(?<UserAgent>[^"}]*)/
| filter Country != "US"
| sort Country, action desc

Filtrer par scripting intersites ou injection SQL

Exécutez cette requête pour filtrer les scriptings intersites ou les injections SQL :

fields @timestamp, terminatingRuleId, action, httpRequest.clientIp as ClientIP, httpRequest.country as Country, terminatingRuleMatchDetails.0.conditionType as ConditionType, terminatingRuleMatchDetails.0.location as Location, terminatingRuleMatchDetails.0.matchedData.0 as MatchedData
| filter ConditionType in["XSS","SQL_INJECTION"]

Séries chronologiques basées sur une règle de terminaison

Exécutez cette requête pour filtrer une série chronologique en fonction d'une règle de terminaison :

#Time Series by Terminating Rule
filter terminatingRuleId = "AWS-AWSManagedRulesCommonRuleSet"
| stats count(*) as requestCount by bin(30m)

Résumer les demandes bloquées par ClientIP, pays, URI et règle

Exécutez cette requête pour résumer les demandes bloquées par ClientIP, pays, URI et règle :

fields httpRequest.clientIp as ClientIP, httpRequest.country as Country, httpRequest.uri as URI, terminatingRuleId as Rule
| filter action = "BLOCK"
| stats count(*) as RequestCount by Country, ClientIP, URI, Rule
| sort RequestCount desc

Principales adresses IP client

Exécutez cette requête pour compter les principales adresses IP client :

stats count(*) as RequestCount by httpRequest.clientIp as ClientIP
| sort RequestCount desc

Principaux pays

Exécutez cette requête pour compter les principaux pays :

stats count(*) as RequestCount by httpRequest.country as Country
| sort RequestCount desc

Principaux hôtes

Exécutez cette requête pour compter les principaux hôtes :

parse @message /\{"name":"[Hh]ost\",\"value":\"(?<Host>[^"}]*)/
| stats count(*) as RequestCount by Host
| sort RequestCount desc

Principales méthodes

Exécutez cette requête pour compter les principales méthodes :

stats count(*)as RequestCount by httpRequest.httpMethod as Method
| sort RequestCount desc

Principales règles de terminaison

Exécutez cette requête pour compter les principales règles de terminaison :

stats count(*) as RequestCount by terminatingRuleId
| sort RequestCount desc

Principaux UserAgents

Exécutez cette requête pour compter les principaux UserAgents :

parse @message /\{"name":"[Uu]ser\-[Aa]gent\",\"value\"\:\"(?<UserAgent>[^"}]*)/
| stats count(*) as RequestCount by UserAgent
| sort RequestCount desc

Demande non terminée par Default_Action ou par des règles dont une action est définie sur ALLOW (AUTORISER)

Exécutez cette requête pour filtrer les demandes qui ne sont pas terminées par une action Default_Action ou par des règles dont une action est définie sur ALLOW (AUTORISER) :

fields @timestamp, terminatingRuleId, action, @message
| filter terminatingRuleId != 'Default_Action' and action != 'ALLOW'
| sort @timestamp desc

Demande avec jeton Captcha non valide

Exécutez cette requête pour filtrer les demandes dont le jeton Captcha n'est pas valide :

fields @timestamp, httpRequest.clientIp, httpRequest.requestId, captchaResponse.failureReason, @message
|filter captchaResponse.failureReason ='TOKEN_MISSING'
| sort @timestamp desc

Demande de blocage par une règle basée sur les taux

Exécutez cette requête pour filtrer les demandes bloquées par une règle basée sur les taux :

fields @timestamp, httpRequest.clientIp, terminatingRuleId, httpRequest.country,@message
| filter terminatingRuleType ="RATE_BASED" ## and webaclId = "arn:aws:wafv2:us-east-1:xxxxxxxx:regional/webacl/waf-test/abcdefghijkl" ## uncomment to filter for specific WebACL
| sort requestCount desc

Filtrer toutes les demandes détectées par AWS Bot Control (ABC)

Exécutez cette requête pour filtrer toutes les demandes détectées par ABC :

fields @timestamp, @message
|filter @message like 'awswaf:managed:aws:bot-control'
| parse @message '"labels":[*]' as Labels
| sort @timestamp desc

Analyse des journaux d'accès AWS WAF avec Amazon Athena

Vous pouvez activer la journalisation des accès AWS WAF directement dans un compartiment Amazon S3. Vous pouvez également utiliser le flux de diffusion Amazon Kinesis Data Firehose pour livrer vos journaux d'accès AWS WAF à un compartiment Amazon S3. Pour savoir comment stocker des journaux dans Amazon S3, consultez la section Comment configurer la journalisation intégrale AWS WAF pour stocker des journaux dans Amazon S3 ?

Lorsque vos journaux d'accès se trouvent dans le compartiment Amazon S3, créez la table AWS WAF pour interroger les journaux et filtrer diverses informations avec Amazon Athena.

Ces requêtes sont des exemples que vous pouvez utiliser pour interroger les journaux AWS WAF avec Athena :

Demandes bloquées contenant des informations sur des règles AWS WAF

Exécutez cette requête Athena pour répertorier toutes les demandes bloquées par une règle AWS WAF :

SELECT timestamp,
    action,
    httpsourcename,
    httpsourceid,
    httprequest.requestID,
    httprequest.clientip,
    webaclid,
    terminatingruleid,
    terminatingruletype,
    rulegrouplist,
    terminatingrulematchdetails
FROM "wafv2"."waf_logs"
WHERE ("action" LIKE 'BLOCK')

Interroger User Agent

Exécutez cette requête Athena pour interroger User Agent :
Remarque : remplacez User-Agent par la valeur de votre UserAgent.

select n.value, count(n.value) as count
from waf_logs
cross join
unnest(
  cast(
    httprequest.headers as ARRAY(ROW(name VARCHAR, value VARCHAR))
    )
  ) as x(n)
where n.name = 'User-Agent'
group by n.value
ORDER BY count(n.value) DESC

URI de demande

Exécutez cette requête Athena pour vérifier l'URI de la demande :

SELECT
"httprequest"."uri"
, "count"(*) "count"
FROM
  waf_logs
WHERE ("action" LIKE 'BLOCK')
GROUP BY "httprequest"."uri"
ORDER BY "count" DESC

Comptage des demandes bloquées en fonction du ClientIP

Exécutez cette requête Athena pour afficher le nombre de demandes bloquées en fonction du ClientIP et du pays :

SELECT
  "httprequest"."clientip"
, "count"(*) "count"
, "httprequest"."country"
FROM
waf_logs
WHERE ("action" LIKE 'BLOCK')
GROUP BY "httprequest"."clientip", "httprequest"."country"
ORDER BY "count" DESC

Afficher le nombre de demandes

Exécutez cette requête Athena pour afficher le nombre de demandes :

SELECT 
  "httprequest"."clientip"
, "count"(*) "count"
,"httprequest"."country"
FROM
 waf_logs
WHERE ("action" LIKE
'BLOCK')
GROUP BY
"httprequest"."clientip", "httprequest"."country"
ORDER BY "count" DESC

Pour d'autres exemples de requêtes Athena, consultez Exemples de requêtes pour les journaux AWS WAF.


Cet article vous a-t-il été utile ?


Avez-vous besoin d'aide pour une question technique ou de facturation ?