La paginazione profonda di endpoint HTTP può essere utilizzata per enumerare molti risultati, consumare risorse o raccogliere contenuti automaticamente. Uno scenario CrowdSec può intercettare richieste con parametro page maggiore di 100 e raggrupparle per indirizzo IP.
Scenario YAML
Creare il file /etc/crowdsec/scenarios/http-deep-pagination.yaml:
type: trigger
name: custom/http-deep-pagination
description: "Rileva richieste HTTP con page maggiore di 100"
filter: >-
evt.Meta.service == 'http' &&
evt.Meta.log_type == 'http_access-log' &&
evt.Meta.source_ip != nil &&
evt.Parsed.http_args != nil &&
evt.Parsed.http_args matches '(^|&)page=0*(10[1-9]|1[1-9][0-9]|[2-9][0-9]{2}|[1-9][0-9]{3,})(&|$)'
groupby: evt.Meta.source_ip
blackhole: 5m
labels:
service: http
behavior: "http:scan"
label: "Deep pagination"
remediation: true
Quali richieste corrispondono?
La regular expression controlla il parametro page nella query string, con separatori & e anche zeri iniziali. I risultati attesi sono:
GET /catalogo?page=99 # non corrisponde
GET /catalogo?page=100 # non corrisponde
GET /catalogo?page=101 # corrisponde
GET /catalogo?page=0101 # corrisponde
GET /catalogo?sort=asc&page=250&lang=it # corrisponde
GET /catalogo?page=1000 # corrisponde
GET /catalogo?pages=500 # non corrisponde
Il confronto richiede evt.Parsed.http_args, che deve essere valorizzato dai parser HTTP. Non tutti i formati di log espongono la query string nello stesso modo: controllare sempre un evento reale con cscli explain. La regex tratta valori numerici interi nel parametro page e non gestisce automaticamente le forme URL-encoded più particolari.
Significato delle direttive
evt.Meta.service == 'http'ehttp_access-loglimitano lo scenario agli access log HTTP.evt.Meta.source_ip != nilevita eventi senza IP sorgente.type: triggerpuò generare un alert al primo URL che supera il limite; è opportuno quando una pagina oltre 100 è sicuramente vietata dall’applicazione.blackhole: 5mevita di generare alert ripetitivi dello stesso bucket per cinque minuti; non determina quanto dura il ban.labels.remediation: trueconsente ai profili CrowdSec di associare una decisione di blocco, se configurati per farlo.
Limiti e precauzioni
Non ogni richiesta con page=101 è malevola: in alcuni siti il parametro è perfettamente valido. Prima di distribuire questa regola su più virtual host, verificare quali applicazioni utilizzano page, se esistono esportazioni legittime e se sia più sensato limitarsi a endpoint selezionati. Se un reverse proxy usa query string normalizzate o riscritture, la corrispondenza può cambiare.
Per limitare il rischio di falsi positivi si possono adottare soglie di frequenza, whitelist mirate ai servizi di monitoraggio oppure filtri sull’endpoint. La durata della decisione di ban resta configurata nei profiles, non nel campo blackhole dello scenario.
Installazione e test
sudo crowdsec -t
sudo cscli explain --file /tmp/pagination-test.log --type apache2 --verbose
sudo cscli scenarios list | grep http-deep-pagination
sudo cscli alerts list
sudo cscli decisions list
# Se la configurazione è valida:
sudo systemctl reload crowdsec
Per il file /tmp/pagination-test.log usare righe di access log reali e rappresentative, verificando sia page=100 sia page=101 e almeno un endpoint applicativo lecito.
Disattivazione
sudo mv /etc/crowdsec/scenarios/http-deep-pagination.yaml /etc/crowdsec/scenarios/http-deep-pagination.yaml.disabled
sudo crowdsec -t && sudo systemctl reload crowdsec
Riferimenti tecnici: formato degli scenari e parser HTTP CrowdSec.