Explications Techniques

Règles Cloudflare WAF qui déclenchent des défis CAPTCHA

Le pare-feu d'application Web (WAF) de Cloudflare permet aux opérateurs de sites de créer des règles qui déclenchent des défis CAPTCHA en fonction d'attributs de requête spécifiques : adresse IP, pays, chemin d'URL, score du bot, en-têtes ou toute combinaison. Comprendre quelles règles déclenchent des défis vous aide à diagnostiquer pourquoi vous voyez un CAPTCHA et à choisir la bonne approche pour le gérer.


Actions de règle WAF qui produisent des CAPTCHA

Les règles Cloudflare WAF prennent en charge plusieurs actions. Trois d’entre eux présentent des défis résolubles :

Action du WAF Que se passe-t-il Statut HTTP Méthode CaptchaAI
Défi géré Cloudflare décide : défi invisible, Turnstile ou JS 503 turnstile
Défi JS Page de défi JavaScript de 5 secondes 503 cloudflare_challenge
Défi interactif CAPTCHA traditionnel (ancien, obsolète) 403 turnstile
Bloquer Difficile 403, pas de défi 403 N/A (non résoluble)
Autoriser Passage, pas de contrôle 200 N/A
Passer Ignorer les règles WAF restantes 200 N/A
Journal Événement de journal, aucune action 200 N/A

Défi géré (le plus courant)

Le défi géré est l'action recommandée par Cloudflare. Il décide de manière adaptative le type de défi par visiteur :

WAF rule matches → Managed Challenge triggered
    ↓
Cloudflare evaluates visitor:
  ├─ Low risk → Invisible pass (no visible challenge)
  ├─ Medium risk → Turnstile widget (click to verify)
  └─ High risk → JavaScript challenge page
    ↓
Successful → cf_clearance cookie issued

Modèles de règles WAF courants

Les opérateurs de sites créent des règles WAF à l'aide du langage d'expression de Cloudflare. Voici les modèles les plus susceptibles de déclencher des CAPTCHA pour le trafic automatisé :

Règles de score des bots

# Challenge traffic with low bot scores
(cf.bot_management.score lt 30)
→ Action: Managed Challenge

# Challenge non-verified bots
(cf.bot_management.score lt 50 and not cf.bot_management.verified_bot)
→ Action: JS Challenge

Les règles de score des robots sont le déclencheur le plus courant pour les outils d'automatisation. Les solveurs API de CaptchaAI reçoivent des scores au niveau humain car ils utilisent de vrais navigateurs.

Règles basées sur les pays

# Challenge traffic from specific countries
(ip.geoip.country in {"CN" "RU" "VN" "IN"})
→ Action: Managed Challenge

# Block specific regions entirely
(ip.geoip.country eq "XX")
→ Action: Block

Règles basées sur le chemin

# Challenge login page access
(http.request.uri.path eq "/login" or http.request.uri.path eq "/signup")
→ Action: Managed Challenge

# Challenge API endpoints
(http.request.uri.path contains "/api/")
→ Action: JS Challenge

Règles basées sur les tarifs

# Challenge after high request rate
(cf.threat_score gt 10 and http.request.uri.path contains "/search")
→ Action: Managed Challenge

Règles basées sur l'en-tête

# Challenge requests with no Accept-Language header
(not http.request.headers["accept-language"])
→ Action: JS Challenge

# Challenge requests with suspicious UA
(http.user_agent contains "python" or http.user_agent contains "curl")
→ Action: Managed Challenge

Règles composées

# Multiple conditions
(cf.bot_management.score lt 30
 and http.request.uri.path contains "/api/"
 and ip.geoip.country ne "US")
→ Action: JS Challenge

Identifier la règle déclenchée

Lorsqu'un challenge CAPTCHA apparaît, vous pouvez identifier la règle de déclenchement à partir de la réponse :

À partir des en-têtes HTTP

import requests

def check_cloudflare_rule_info(url):
    """Extract WAF rule information from Cloudflare challenge response."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    response = requests.get(url, headers=headers, timeout=15, allow_redirects=False)

    info = {
        "status": response.status_code,
        "cf_ray": response.headers.get("cf-ray", ""),
        "cf_cache_status": response.headers.get("cf-cache-status", ""),
        "server": response.headers.get("server", ""),
    }

    # Challenge-specific info
    html = response.text

    if response.status_code == 503:
        if "jschl" in html:
            info["challenge_type"] = "JS Challenge (IUAM or WAF rule)"
        elif "challenge-platform" in html:
            info["challenge_type"] = "Managed Challenge"
        elif "cf-turnstile" in html:
            info["challenge_type"] = "Turnstile (Managed Challenge)"

    elif response.status_code == 403:
        if "cf-ray" in str(response.headers):
            info["challenge_type"] = "WAF Block (no challenge)"
        else:
            info["challenge_type"] = "Origin 403 (not Cloudflare)"

    return info

Depuis l'identifiant Cloudflare Ray

Chaque réponse Cloudflare inclut un en-tête cf-ray. Les opérateurs de site peuvent utiliser ce Ray ID dans le tableau de bord de Cloudflare (Sécurité > Événements) pour voir exactement quelle règle s'est déclenchée et quelle action a été entreprise.


Résoudre les défis déclenchés par le WAF

Stratégie basée sur le type de défi

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_cloudflare_challenge(url, challenge_type):
    """Solve Cloudflare challenge based on WAF rule action."""

    if challenge_type == "managed_challenge":
        # Managed Challenge typically renders as Turnstile
        method = "turnstile"
        sitekey = extract_turnstile_sitekey(url)
    elif challenge_type == "js_challenge":
        # JavaScript Challenge page
        method = "cloudflare_challenge"
        sitekey = "managed"
    else:
        raise ValueError(f"Unknown challenge type: {challenge_type}")

    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": method,
        "sitekey": sitekey,
        "pageurl": url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]

    raise TimeoutError("Challenge solve timed out")


def extract_turnstile_sitekey(url):
    """Fetch page and extract Turnstile sitekey."""
    import re
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
    }
    response = requests.get(url, headers=headers, timeout=15)
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', response.text)
    return match.group(1) if match else None

Noeud.js

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveWAFChallenge(url, challengeType) {
  const method =
    challengeType === "js_challenge" ? "cloudflare_challenge" : "turnstile";
  const sitekey =
    challengeType === "js_challenge" ? "managed" : await extractSitekey(url);

  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method,
      sitekey,
      pageurl: url,
      json: 1,
    },
  });

  const taskId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId, json: 1 },
    });

    if (result.data.status === 1) {
      return result.data.request;
    }
  }

  throw new Error("Challenge solve timed out");
}

async function extractSitekey(url) {
  const response = await axios.get(url, {
    headers: {
      "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0",
    },
  });
  const match = response.data.match(/data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/);
  return match ? match[1] : null;
}

Modifications des règles WAF et leurs effets

Les opérateurs de sites ajustent fréquemment les règles WAF. Ces changements affectent l'automatisation :

Changement Effet sur l'automatisation Comment détecter
Règle ajoutée Un nouveau défi apparaît sur les chemins qui ont fonctionné Surveiller les changements d'état de 503/403
Règle supprimée Le défi disparaît 200 là où 503 était avant
Action signalée (bloc → géré) Un défi résoluble devient un bloc difficile 403 au lieu de 503
Action détendue (Bloc → Géré) Le bloc dur devient un défi résoluble 503 avec page de défi
Seuil modifié (score du bot 30 → 50) Plus de demandes contestées Augmentation de la fréquence des défis
Portée du chemin modifiée Différentes URL concernées Les nouveaux chemins génèrent des défis

Stratégie de surveillance

import requests
import time

def monitor_cloudflare_protection(urls, interval=3600):
    """Monitor protection changes across URLs."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    last_status = {}

    while True:
        for url in urls:
            try:
                response = requests.get(
                    url, headers=headers, timeout=15, allow_redirects=False
                )
                status = response.status_code
                has_challenge = status == 503 or "cf-turnstile" in response.text

                current = {"status": status, "challenge": has_challenge}
                previous = last_status.get(url)

                if previous and current != previous:
                    print(f"[CHANGE] {url}")
                    print(f"  Before: {previous}")
                    print(f"  After:  {current}")

                last_status[url] = current

            except requests.RequestException as e:
                print(f"[ERROR] {url}: {e}")

        time.sleep(interval)

Dépannage

Symptôme Règle WAF probable Corriger
Défi uniquement sur /login Règle basée sur le chemin Résoudre le défi pour ce chemin
Défi provenant uniquement des adresses IP du centre de données Score du bot ou règle de réputation IP Utilisez des proxys résidentiels ou résolvez un défi
Le défi varie selon les pays Règle basée sur le pays Utilisez un proxy dans le pays autorisé ou résolvez
Défi après N requêtes Règle basée sur le taux Réduisez le taux de demandes ou résolvez chaque défi
Défiez toujours JS (jamais Turnstile) Action JS Challenge (non gérée) Utiliser la méthode cloudflare_challenge
403 sans défi Action de blocage (non résoluble) Modifier l'adresse IP, les en-têtes ou le modèle de demande

Questions fréquemment posées

Puis-je voir quelles règles WAF un site utilise ?

Non. Les règles WAF sont privées et appartiennent à l'opérateur du site. Vous ne pouvez déduire des règles qu'à partir du comportement : quels chemins déclenchent des défis, à partir de quelles adresses IP et quel type de défi apparaît.

Les règles WAF s'appliquent-elles à tous les forfaits Cloudflare ?

Les règles WAF personnalisées sont disponibles sur tous les forfaits payants (Pro, Business, Enterprise). Les forfaits gratuits ont des règles WAF limitées. Cependant, Managed Challenge est disponible sur tous les forfaits, y compris Free.

Les règles WAF peuvent-elles déclencher différents défis pour différents chemins ?

Oui. Chaque règle WAF peut avoir une action différente et correspondre à des chemins différents. Un site peut utiliser Managed Challenge pour /login et JS Challenge pour les points de terminaison /api/.

À quelle fréquence les sites modifient-ils leurs règles WAF ?

Cela varie. Les sites de commerce électronique ajustent souvent les règles lors des événements de vente. Les sites soucieux de leur sécurité peuvent mettre à jour leurs règles chaque semaine. La plupart des sites modifient rarement les règles après la configuration initiale.

La résolution d’un défi WAF affecte-t-elle les demandes futures ?

Oui. Après résolution, le cookie cf_clearance laisse passer les requêtes suivantes sans contestation pendant environ 30 minutes. Le cookie est lié à votre adresse IP et à votre agent utilisateur.


Résumé

Les règles Cloudflare WAF déclenchent des défis CAPTCHA en fonction de conditions configurables : score du bot, pays, chemin, en-têtes ou taux. L'action la plus courante est le défi géré, que Cloudflare restitue de manière adaptative sous la forme d'un défi invisible, Turnstile ou JS. Résolvez-les avecCaptchaAIen utilisant la méthode turnstile ou cloudflare_challenge selon ce qui est rendu. Les blocs durs (403) des règles WAF ne peuvent pas être résolus : modifiez plutôt votre modèle de requête ou votre adresse IP.

Articles connexes

Les commentaires sont désactivés pour cet article.