~/docs/CloudFlare/Bypass+mitigation
文章探讨了通过Cloudflare和Nginx增强网站安全性的方法,包括创建脚本更新Cloudflare IP列表、配置防火墙规则以限制非Cloudflare流量,并讨论了防止IP泄露及应对SSRF和DDoS攻击的策略。 2025-12-15 16:32:22 Author: blog.lobsec.com(查看原文) 阅读量:6 收藏

Lo sappiamo tutti: in un panorama digitale in continua evoluzione, la sicurezza informatica non è più un optional, ma un pilastro fondamentale di qualsiasi infrastruttura web seria. La recente decisione di migrare l’infrastruttura di questo blog sotto la “protezione” di Cloudflare non è stata solo una mossa per l’ottimizzazione delle performance, ma un passo per rinforzare la postura di sicurezza.

Questo post esplorerà due aspetti critici: come è stato tecnicamente integrato Cloudflare con la configurazione Nginx, quali sono i limiti di questa soluzione, come mitigarli e gli attacchi più comuni in uno scenario di offuscamento delle risorse esposte.

Cloudflare e Nginx

Per prima cosa è stato creato uno script che permetta di interrogare e scaricare le liste degli IP della CDN di Cloudflare: questo script può essere inserito in un job cron per tenere costantemente aggiornate le subnet.

#!/bin/bash

# File di configurazione Nginx in cui verranno salvate le direttive 'allow'
NGINX_ALLOW_CONF="/etc/nginx/conf.d/cloudflare_allow_ips.conf"

# URL da cui scaricare gli IP di Cloudflare (IPv4 e IPv6)
IPV4_URL="https://www.cloudflare.com/ips-v4/"
IPV6_URL="https://www.cloudflare.com/ips-v6/"

# Percorso temporaneo per i file scaricati
TEMP_IPV4=$(mktemp)
TEMP_IPV6=$(mktemp)

# 1. Scarica gli IP di Cloudflare
echo "Scarico gli intervalli IP Cloudflare..."
curl -s $IPV4_URL > $TEMP_IPV4
if [ $? -ne 0 ]; then
    echo "ERRORE: Impossibile scaricare gli IP IPv4 di Cloudflare."
    rm -f $TEMP_IPV4 $TEMP_IPV6
    exit 1
fi

curl -s $IPV6_URL > $TEMP_IPV6
if [ $? -ne 0 ]; then
    echo "ERRORE: Impossibile scaricare gli IP IPv6 di Cloudflare."
    rm -f $TEMP_IPV4 $TEMP_IPV6
    exit 1
fi

# 2. Genera il nuovo file di configurazione Nginx
echo "Generazione del file di configurazione Nginx..."
cat <<EOF > $NGINX_ALLOW_CONF
# Aggiornato da script il $(date)
#
# Permetti solo il traffico Cloudflare (IPv4)
$(cat $TEMP_IPV4 | sed 's/^/allow /g; s/$/;/g')

# Permetti solo il traffico Cloudflare (IPv6)
$(cat $TEMP_IPV6 | sed 's/^/allow /g; s/$/;/g')

# Blocca tutto il traffico restante
deny all;
EOF

# 3. Pulisci i file temporanei
rm -f $TEMP_IPV4 $TEMP_IPV6

Lo script crea un file dentro la /etc/nginx/conf.d/ chiamato cloudflare_allow_ips.conf che avrà questa sintassi

# Aggiornato da script il Thu Dec 11 18:55:48 UTC 2025
#
# Permetti solo il traffico Cloudflare (IPv4)
allow 173.245.48.0/20;
allow 103.21.244.0/22;
allow 103.22.200.0/22;
allow 103.31.4.0/22;
allow 141.101.64.0/18;
allow 108.162.192.0/18;
allow 190.93.240.0/20;
allow 188.114.96.0/20;
allow 197.234.240.0/22;
allow 198.41.128.0/17;
allow 162.158.0.0/15;
allow 104.16.0.0/13;
allow 104.24.0.0/14;
allow 172.64.0.0/13;
allow 131.0.72.0/22;

# Permetti solo il traffico Cloudflare (IPv6)
allow 2400:cb00::/32;
allow 2606:4700::/32;
allow 2803:f800::/32;
allow 2405:b500::/32;
allow 2405:8100::/32;
allow 2a06:98c0::/29;
allow 2c0f:f248::/32;

# Blocca tutto il traffico restante
deny all;

Il file dovrà successivamente essere inserito nel blocco http della configurazione di nginx (/etc/nginx/nginx.conf) se si vuole che le impostazioni vengano implementate su tutti i virtual host, diversamente dovranno essere inserite nei blocchi di configurazioni del singolo virtual host.

Migliorie aggiuntive

Sebbene CF aggiunga molti di questi headers ritengo essere importante aggiungerli comunque alle configurazioni originali: questo perchè laddove si volesse anche solo momentaneamente bypassare il proxy, si garantirebbe un buon livello di sicurezza crittografica di transito.

Headers

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "interest-cohort=()" always; # blocca FLoC
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

TLS

Limitate le versioni TLS, andando a deprecare quelle obsolete

ssl_protocols TLSv1.2 TLSv1.3;

Cipher

ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';

I problemi

Per il momento abbiamo esplorato come limitare tutte le connessioni in ingresso sull’nginx: tuttavia questo non è sufficiente in quanto il server, se un attaccante fosse in grado di scoprire il vero indirizzo dietro il WAF (in seguito vedremmo un esempio pratico di come fare), accetterà comunque tutte le connessioni in ingresso rendendolo di fatto passibile ad attacchi di tipo DDoS, SSRF, Amplification, etc.

Dimostrazione di come le connessioni dirette all’IP reale del server non vengano bloccate

La soluzione ottimale è quella di agire direttamente sul firewall di sistema, andando a bloccare immediatamente il traffico in ingresso laddove si dovesse presentare da un IP non appartenente alla CDN.

Cloudflare e IPTables

Lo script in bash scarica gli intervalli IP di Cloudflare (IPv4 e IPv6) e aggiunge le regole corrispondenti a iptables e ip6tables per permettere solo il traffico in ingresso proveniente da quegli indirizzi sulle porte 80 (HTTP) e 443 (HTTPS).

Lo script include anche una funzione per pulire le regole precedenti prima di aggiungere le nuove, rendendolo ideale per l’esecuzione periodica (ad esempio, tramite cron).

#!/bin/bash

# ===============================================
# Configurazione
# ===============================================
IPTABLES_V4_URL="https://www.cloudflare.com/ips-v4/"
IPTABLES_V6_URL="https://www.cloudflare.com/ips-v6/"
LOG_FILE="/var/log/cloudflare_iptables.log"
# Iniziale delle catene personalizzate per una facile pulizia
IPT_CHAIN="CLOUDFLARE_V4"
IP6T_CHAIN="CLOUDFLARE_V6"

# Porte da permettere
PORTS="80,443"

# ===============================================
# Funzioni
# ===============================================

# Funzione per loggare i messaggi
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Funzione per pulire le regole esistenti di Cloudflare
cleanup_existing_rules() {
    log "Pulizia delle catene e delle regole esistenti di Cloudflare..."

    # 1. Pulizia catena IPv4 (iptables)
    iptables -D INPUT -p tcp -m multiport --dports "$PORTS" -j "$IPT_CHAIN" 2>/dev/null
    iptables -F "$IPT_CHAIN" 2>/dev/null
    iptables -X "$IPT_CHAIN" 2>/dev/null

    # 2. Pulizia catena IPv6 (ip6tables)
    ip6tables -D INPUT -p tcp -m multiport --dports "$PORTS" -j "$IP6T_CHAIN" 2>/dev/null
    ip6tables -F "$IP6T_CHAIN" 2>/dev/null
    ip6tables -X "$IP6T_CHAIN" 2>/dev/null
    
    log "Pulizia completata."
}

# Funzione principale per aggiornare le regole
update_cloudflare_rules() {
    # 1. Creazione catene personalizzate
    iptables -N "$IPT_CHAIN" || log "La catena $IPT_CHAIN esiste già o errore nella creazione."
    ip6tables -N "$IP6T_CHAIN" || log "La catena $IP6T_CHAIN esiste già o errore nella creazione."

    # 2. Aggiunta delle regole alle catene INPUT (solo se non esistono già)
    # L'uso di "-C" (Check) è più sicuro
    if ! iptables -C INPUT -p tcp -m multiport --dports "$PORTS" -j "$IPT_CHAIN" 2>/dev/null; then
        iptables -I INPUT -p tcp -m multiport --dports "$PORTS" -j "$IPT_CHAIN"
        log "Regola di salto IPv4 aggiunta alla catena INPUT."
    else
        log "Regola di salto IPv4 già esistente nella catena INPUT."
    fi

    if ! ip6tables -C INPUT -p tcp -m multiport --dports "$PORTS" -j "$IP6T_CHAIN" 2>/dev/null; then
        ip6tables -I INPUT -p tcp -m multiport --dports "$PORTS" -j "$IP6T_CHAIN"
        log "Regola di salto IPv6 aggiunta alla catena INPUT."
    else
        log "Regola di salto IPv6 già esistente nella catena INPUT."
    fi

    # 3. Scaricamento IP Cloudflare e aggiunta delle regole IPv4
    log "Scarico e applico gli IP IPv4..."
    local ip_count_v4=0
    if curl -sS "$IPTABLES_V4_URL" | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$' | while IFS= read -r ip; do
        iptables -A "$IPT_CHAIN" -s "$ip" -j ACCEPT
        ip_count_v4=$((ip_count_v4 + 1))
    done; then
        log "Aggiunte $ip_count_v4 regole IPv4."
    else
        log "ERRORE: Impossibile scaricare o applicare gli IP IPv4."
        return 1
    fi

    # 4. Scaricamento IP Cloudflare e aggiunta delle regole IPv6
    log "Scarico e applico gli IP IPv6..."
    local ip_count_v6=0
    if curl -sS "$IPTABLES_V6_URL" | grep -E '^[0-9a-fA-F:/]+/[0-9]{1,3}$' | while IFS= read -r ip; do
        ip6tables -A "$IP6T_CHAIN" -s "$ip" -j ACCEPT
        ip_count_v6=$((ip_count_v6 + 1))
    done; then
        log "Aggiunte $ip_count_v6 regole IPv6."
    else
        log "ERRORE: Impossibile scaricare o applicare gli IP IPv6."
        return 1
    fi
    
    # 5. Regola di default: DROP per tutto il resto
    # Questa regola di DROP deve essere l'ultima nelle catene CLOUDFLARE_V4 e CLOUDFLARE_V6.
    # Attenzione: Questo blocca *tutto* il traffico non-Cloudflare verso le porte 80/443!
    iptables -A "$IPT_CHAIN" -j DROP
    ip6tables -A "$IP6T_CHAIN" -j DROP
    log "Aggiunta regola finale DROP nelle catene di Cloudflare."

    # 6. Salvataggio delle regole (necessario su Ubuntu per la persistenza)
    if command -v iptables-save >/dev/null 2>&1 && command -v netfilter-persistent >/dev/null 2>&1; then
        log "Salvataggio delle regole tramite netfilter-persistent..."
        netfilter-persistent save
    elif command -v iptables-save >/dev/null 2>&1; then
        log "Salvataggio delle regole con iptables-save/ip6tables-save (richiede configurazione)."
        # Potrebbe essere necessario un comando specifico per la tua configurazione di persistenza,
        # come 'service netfilter-persistent save' o 'iptables-save > /etc/iptables/rules.v4'
        # Aggiungo un placeholder comune per sistemi più vecchi o generici:
        # iptables-save > /etc/iptables/rules.v4
        # ip6tables-save > /etc/iptables/rules.v6
    else
        log "ATTENZIONE: Nessun comando di salvataggio persistente trovato (iptables-save o netfilter-persistent)."
    fi

    log "Aggiornamento Cloudflare completato con successo."
}

# ===============================================
# Esecuzione
# ===============================================

# Esegue prima la pulizia
cleanup_existing_rules

# Esegue l'aggiornamento
update_cloudflare_rules

exit 0

Il risultato

In questo caso, tutte le richieste dirette all’IP reale del server, vengono bloccate

La sicurezza perimetrale sotto esame: abuso del Pingback XML-RPC e rivelazione dell’IP reale

Fino ad ora abbiamo visto come l’adozione di una CDN come Cloudflare è prassi standard per la mitigazione dei vettori di attacco di Layer 7 e per l’occultamento dell’indirizzo IP d’origine. Implementare un reverse proxy di questo tipo è un passo cruciale per la difesa, ma la sicurezza di questa configurazione dipende intrinsecamente dalla configurazione del server retrostante. Una delle tecniche di fingerprinting più efficaci e storicamente sfruttate contro le installazioni WordPress è l’abuso della funzionalità Pingback tramite l’endpoint XML-RPC.

I. Il Vettore d’Attacco: il Pingback

La funzione Pingback è un meccanismo intrinseco del protocollo XML-RPC di WordPress, progettato per notificare un blog quando un altro blog linka il suo contenuto. Quando un sistema Pingback viene invocato, il server target (il nostro server d’origine protetto da Cloudflare) esegue una richiesta HTTP in uscita verso l’URL specificato nel payload della richiesta XML-RPC.

Il vettore di attacco sfrutta il fatto che, in una configurazione standard, le richieste Pingback in uscita vengono risolte ed eseguite direttamente dall’indirizzo IP del server d’origine, ignorando completamente il proxy e i range IP della CDN.

L’attaccante esegue i seguenti passi per la Rivelazione dell’IP:

  1. Individuazione dell’endpoint: l’attaccante invia una richiesta POST all’endpoint XML-RPC del sito WordPress, tipicamente situato in /xmlrpc.php.
  2. Preparazione del payload: la richiesta contiene il metodo pingback.ping e indirizza il server d’origine a connettersi a un server Listener controllato dall’attaccante (l’indirizzo è iniettato nel parametro targetUri).
  3. Rivelazione dell’IP: quando il server WordPress processa questa richiesta, tenta di inviare la notifica Pingback al Listener. Il Listener, monitorando i log delle connessioni in ingresso, registra l’indirizzo IP del mittente della connessione. Questo indirizzo IP è l’indirizzo IP reale e nascosto del server d’origine.

Esempio di Payload XML-RPC Manipolato

Il payload per l’attacco è strutturato come segue (dove listener-attacker.com è il server controllato):

L’immagine è volutamente stata creata con una IA

II. Implicazioni aggravanti: SSRF e amplificazione DDoS

La vulnerabilità Pingback non è limitata alla sola rivelazione dell’IP. La sua natura, che permette l’inizializzazione di connessioni HTTP arbitrarie da parte del server target, la rende un vettore ideale per attacchi di SSRF e DDoS per Amplificazione.

Server-Side Request Forgery (SSRF)

Poiché il Pingback abilita il server d’origine a connettersi a qualsiasi URI specificato dall’attaccante, anche URI interni o locali, la funzionalità si trasforma in un vettore SSRF. Un attaccante può tentare di indirizzare il server a porte e servizi accessibili solo dalla rete interna o dalla loopback interface (e.g., 127.0.0.1 o localhost).

Questo consente l’enumerazione di servizi interni (come metadati cloud, API locali di gestione, o pannelli di amministrazione non esposti pubblicamente) e, in combinazione con servizi vulnerabili, può portare a esfiltrazione di dati, attacchi port scanning interni o esecuzione di comandi remoti. La capacità di manipolare il targetUri per puntare a risorse non-pubbliche è la chiave per trasformare il Pingback in un problema di sicurezza interna.

Attacchi di amplificazione DDoS

Un’ulteriore e più diffusa conseguenza è l’utilizzo del meccanismo XML-RPC Pingback per attacchi di Denial of Service (DDoS) distribuiti e riflessi. Un attaccante può creare un botnet di server WordPress vulnerabili. Inviando migliaia di richieste Pingback simultanee, tutte indirizzate (tramite il targetUri) alla vittima finale, ogni server WordPress sfrutta la sua larghezza di banda per inviare una richiesta HTTP in uscita, amplificando il traffico DDoS e mascherando la fonte reale dell’attacco.

III. PoC

Per dimostrare l’efficacia di questa tecnica, un professionista può eseguire un test attivo (PoC) che richiede un server Listener controllato esternamente e l’utilizzo di strumenti HTTP standard.

  1. Setup del Server Listener: configurare un server esterno (con FQDN risolvibile, es. listener-test.com) in grado di registrare l’indirizzo IP d’origine di qualsiasi connessione TCP/HTTP in entrata. Strumenti semplici come netcat o uno script Python in ascolto su una porta specifica sono sufficienti.
  2. Esecuzione del Test con curl: inviare la richiesta XML-RPC manipolata al server WordPress protetto, utilizzando il FQDN del Listener come destinazione del Pingback.
# Eseguito da una workstation di testing 
ATTACKER_URI="http://listener-test.com:8080/test-pingback" 
TARGET_URI="https://sito-protetto.com/post-arbitrario" 
PAYLOAD='<?xml version="1.0" encoding="iso-8859-1"?> 
<methodCall> 
    <methodName>pingback.ping</methodName> </methodCall>' 

curl -X POST -H 'Content-Type: text/xml' \ --data "$PAYLOAD" \ https://sito-protetto.com/xmlrpc.php

Analisi dei Risultati: Se il log del Listener mostra un accesso HTTP proveniente da un IP non appartenente ai range Cloudflare, la vulnerabilità di IP-leakage è confermata.

IV. Strategie di mitigazione

La mitigazione più robusta per questi exploit consiste nel blocco completo dell’accesso all’endpoint /xmlrpc.php.

Questo può essere realizzato tramite:

  • Regole Firewall (come iptables): utilizzare il meccanismo descritto nello script precedente per permettere il traffico in ingresso solo dai range IP ufficiali di Cloudflare per le porte 80 e 443. Questo assicura che qualsiasi richiesta a /xmlrpc.php non proveniente dal CDN venga bloccata a livello di rete.
  • Disabilitazione Funzionale: Se l’XML-RPC e il Pingback non sono strettamente necessari per le funzionalità del sito, disabilitarli completamente a livello di codice o tramite plugin di sicurezza.

EOF


文章来源: https://blog.lobsec.com/2025/12/ladozione-di-una-cdn-e-prassi-standard-per-la-mitigazione-dei-vettori-di-attacco-di-layer-7-e-per-loccultamento-dellindirizzo-ip-dorigine-origin-ip/
如有侵权请联系:admin#unsafe.sh