Abonnez-vous pour recevoir des notifications sur les nouveaux articles :

Intégration de Turnstile au pare-feu WAF de Cloudflare afin de vérifier les requêtes fetch

2023-12-18

Lecture: 4 min.
Cet article est également disponible en English, en 繁體中文, en Deutsch, en 日本語, en 한국어, en Português, en Español, en Polski et en 简体中文.

Il y a deux mois, nous avons publié Cloudflare Turnstile en disponibilité générale, offrant ainsi aux propriétaires de sites web du monde entier une solution simple pour repousser les bots, sans jamais afficher un CAPTCHA. Turnstile permet à n'importe quel propriétaire de site web d'intégrer, avec un simple extrait de code, une vérification par Cloudflare, n'entraînant pas de frustration pour les utilisateurs ; cette fonctionnalité permet d'assurer facilement que seul le trafic d'origine humaine est autorisé. En plus de protéger l'interface d'un site web, Turnstile permet également aux administrateurs web de renforcer les appels d'API initiés par le navigateur (AJAX), exécutés en arrière-plan. Ces API sont fréquemment utilisées par les applications web dynamiques pour pages uniques, à l'image de celles créées avec React, Angular et Vue.js.

Integrating Turnstile with the Cloudflare WAF to challenge fetch requests

Aujourd'hui, nous sommes ravis d'annoncer que nous avons intégré Turnstile au pare-feu d'applications web (WAF) de Cloudflare. Cela signifie que les administrateurs web peuvent ajouter l'extrait de code Turnstile à leur site web, puis configurer le pare-feu WAF de Cloudflare afin de gérer ces requêtes. Cette configuration est entièrement personnalisable à l'aide des règles de pare-feu WAF. Vous pouvez, par exemple, permettre à un utilisateur authentifié par Turnstile d'interagir avec tous les points de terminaison d'API d'une application sans autre vérification, ou vous pouvez configurer certains points de terminaison sensibles, tels que Login, afin de toujours imposer une vérification.

Vérification des requêtes fetch dans le pare-feu WAF de Cloudflare

Des millions de sites web protégés par le pare-feu WAF de Cloudflare utilisent nos vérifications JS, Managed Challenge et Interactive Challenge pour arrêter les bots, tout en autorisant le trafic d'origine humaine. Pour chacune de ces vérifications, Cloudflare intercepte la requête correspondante et répond avec une page HTML affichée par le navigateur, sur laquelle l'utilisateur doit effectuer une tâche simple afin de démontrer qu'il est humain. Lorsqu'un utilisateur réussit une vérification, il reçoit un cookie cf_clearance qui indique à Cloudflare qu'un utilisateur a réussi une vérification, le type de vérification et la date à laquelle la vérification a été réussie. Un cookie d'autorisation ne peut pas être partagé entre des utilisateurs, et il est uniquement valide pour la durée définie par le client Cloudflare depuis son tableau de bord de paramètres de sécurité.

Ce processus s'avère efficace, sauf lorsqu'un navigateur reçoit une demande de vérification suivant une requête fetch et que le navigateur n'a encore jamais effectué de vérification. Après une requête fetch ou une requête HTTP XML (XHR), le navigateur s'attend à recevoir du texte simple (au format JSON ou XML) et ne peut pas afficher le code HTML nécessaire à l'exécution d'une vérification.

À titre d'exemple, imaginons que le propriétaire d'une pizzeria a créé un formulaire de commande en ligne dans React, avec une page de paiement permettant de transmettre les données à un point de terminaison d'API assurant le traitement des paiements. Lorsqu'un utilisateur consulte le formulaire web afin de saisir les informations de sa carte de paiement, il peut effectuer une vérification Managed Challenge ; toutefois, lorsque l'utilisateur transmet les informations de sa carte de paiement au moyen d'une requête fetch, le navigateur n'exécute pas le code nécessaire pour effectuer cette vérification. Le seul choix dont dispose le propriétaire de la pizzeria pour traiter les requêtes suspectes (mais potentiellement légitimes) consiste à les bloquer, ce qui risque d'entraîner des faux positifs susceptibles de faire perdre une vente au restaurant.

C'est ici que Turnstile peut vous aider. Turnstile permet à n'importe quel utilisateur d'Internet d'intégrer une vérification Cloudflare sur n'importe quelle page de son site web. Jusqu'à aujourd'hui, le résultat de Turnstile n'était qu'un jeton à usage unique. Pour permettre aux clients d'imposer des vérifications pour ces requêtes fetch, Turnstile peut désormais émettre un cookie d'autorisation pour le domaine sur lequel il est intégré. Les clients peuvent configurer leur vérification dans la page HTML avant une requête fetch, en autorisant au préalable le visiteur à interagir avec l'API de paiement.

Mode Pre-Clearance de Turnstile

Reprenons maintenant l'exemple de notre pizzeria. Les trois principaux avantages qu'offre l'utilisation de la fonction Pre-Clearance pour l'intégration de Turnstile au pare-feu WAF de Cloudflare sont les suivants :

  1. Amélioration de l'expérience utilisateur : la fonctionnalité de vérification intégrée de Turnstile peut s'exécuter en arrière-plan pendant que le visiteur saisit les informations de sa carte de paiement.

  2. Blocage d'un plus grand nombre de requêtes à la périphérie : puisque Turnstile émet désormais un cookie d'autorisation pour le domaine sur lequel il est intégré, le propriétaire de la pizzeria peut définir une règle personnalisée afin d'imposer une vérification Managed Challenge pour chaque requête adressée à l'API de paiement. Ceci garantit que les attaques automatisées qui tentent de cibler directement l'API de paiement sont arrêtées par Cloudflare avant qu'elles ne puissent atteindre l'API.

  3. (Facultatif) Sécurisation de l'action et de l'utilisateur : aucune modification du code backend n'est nécessaire pour bénéficier de la fonctionnalité Pre-Clearance. Cependant, une intégration plus poussée de Turnstile renforcera la sécurité de l'API intégrée. Le propriétaire de la pizzeria peut ajuster son formulaire de paiement pour valider le jeton Turnstile reçu, en veillant à ce que chaque tentative de paiement soit validée individuellement par Turnstile, afin de protéger son point de terminaison de paiement contre le piratage de session.

Un widget Turnstile pour lequel la fonctionnalité Pre-Clearance est activée générera toujours des jetons Turnstile, offrant aux clients la possibilité de choisir si un point de terminaison est suffisamment critique pour nécessiter une vérification de la sécurité à chaque requête qui lui est adressée, ou seulement une fois par session. Les cookies d'autorisation émis par un widget Turnstile sont automatiquement appliqués à la zone de Cloudflare à laquelle est intégré le widget Turnstile, sans qu'aucune configuration ne soit nécessaire. L'heure d'autorisation pour laquelle le jeton est valide est toujours contrôlée par l'heure « Challenge Passage » spécifique à la zone.

Mise en œuvre de Turnstile avec la fonctionnalité Pre-Clearance

Examinons maintenant une mise en œuvre concrète, avec une implémentation simple. Avant de commencer, nous avons configuré une application de démonstration simple, dans laquelle nous émulons un frontend qui communique avec un backend sur un point de terminaison /your-api.

À cette fin, nous disposons du code suivant :

Nous avons créé un bouton. Lorsqu'un utilisateur clique dessus, Cloudflare transmet une requête fetch() au point de terminaison /your-api, puis affiche le résultat dans le conteneur de la réponse.

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Turnstile Pre-Clearance Demo </title>
</head>
<body>
  <main class="pre-clearance-demo">
    <h2>Pre-clearance Demo</h2>
    <button id="fetchBtn">Fetch Data</button>
    <div id="response"></div>
</main>

<script>
  const button = document.getElementById('fetchBtn');
  const responseDiv = document.getElementById('response');
  button.addEventListener('click', async () => {
  try {
    let result = await fetch('/your-api');
    if (result.ok) {
      let data = await result.json();
      responseDiv.textContent = JSON.stringify(data);
    } else {
      responseDiv.textContent = 'Error fetching data';
    }
  } catch (error) {
    responseDiv.textContent = 'Network error';
  }
});
</script>

Considérons maintenant que nous avons mis en place une règle du pare-feu WAF de Cloudflare qui protège le point de terminaison /your-api avec une vérification Managed Challenge.

En raison de cette règle, l'application que nous venons d'écrire va échouer, pour la raison décrite plus haut (le navigateur attend une réponse JSON, mais reçoit à la place la page de test au format HTML).

Si nous examinons l'onglet Network (Réseau), nous voyons que la requête transmise au point de terminaison /your-api a reçu une réponse 403.

Lors de l'inspection, l'en-tête Cf-Mitigated indique que la réponse a été soumise à une vérification par le pare-feu de Cloudflare, car le visiteur n'a pas réussi de vérification auparavant.

Pour remédier à ce problème dans notre application, nous avons configuré un widget Turnstile en mode Pre-Clearance pour le fichier SiteKey Turnstile que nous souhaitons utiliser.

Dans notre application, nous passons outre la fonction fetch() pour invoquer Turnstile lorsqu'une réponse Cf-Mitigated a été reçue.

Il se passe beaucoup de choses dans l'extrait de code ci-dessus : tout d'abord, nous créons un élément superposé masqué, puis nous passons outre la fonction fetch() du navigateur. La fonction fetch() est modifiée afin d'inspecter l'en-tête Cf-Mitigated à la recherche de « challenge » (vérification). Si une vérification est imposée, le résultat initial sera un échec ; au lieu de cela, une page Turnstile (avec fonction Pre-Clearance activée) sera affichée dans notre application web . Une fois la vérification Turnstile terminée, nous réessaierons la requête précédente lorsque Turnstile aura obtenu le cookie cf_clearance pour franchir le pare-feu WAF de Cloudflare.

<script>
turnstileLoad = function () {
  // Save a reference to the original fetch function
  const originalFetch = window.fetch;

  // A simple modal to contain Cloudflare Turnstile
  const overlay = document.createElement('div');
  overlay.style.position = 'fixed';
  overlay.style.top = '0';
  overlay.style.left = '0';
  overlay.style.right = '0';
  overlay.style.bottom = '0';
  overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  overlay.style.border = '1px solid grey';
  overlay.style.zIndex = '10000';
  overlay.style.display = 'none';
  overlay.innerHTML =       '<p style="color: white; text-align: center; margin-top: 50vh;">One more step before you proceed...</p><div style=”display: flex; flex-wrap: nowrap; align-items: center; justify-content: center;” id="turnstile_widget"></div>';
  document.body.appendChild(overlay);

  // Override the native fetch function
  window.fetch = async function (...args) {
      let response = await originalFetch(...args);

      // If the original request was challenged...
      if (response.headers.has('cf-mitigated') && response.headers.get('cf-mitigated') === 'challenge') {
          // The request has been challenged...
          overlay.style.display = 'block';

          await new Promise((resolve, reject) => {
              turnstile.render('#turnstile_widget', {
                  'sitekey': ‘YOUR_TURNSTILE_SITEKEY',
                  'error-callback': function (e) {
                      overlay.style.display = 'none';
                      reject(e);
                  },
                  'callback': function (token, preClearanceObtained) {
                      if (preClearanceObtained) {
                          // The visitor successfully solved the challenge on the page. 
                          overlay.style.display = 'none';
                          resolve();
                      } else {
                          reject(new Error('Unable to obtain pre-clearance'));
                      }
                  },
              });
          });

          // Replay the original fetch request, this time it will have the cf_clearance Cookie
          response = await originalFetch(...args);
      }
      return response;
  };
};
</script>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=turnstileLoad" async defer></script>

Lors de la résolution du widget Turnstile, l'élément superposé disparaît et le résultat d'API concerné par la requête est affiché avec succès :

Pre-Clearance est disponible pour tous les clients de Cloudflare

Tous les utilisateurs de Cloudflare ayant souscrit à l'offre gratuite ou une offre supérieure peuvent utiliser gratuitement Turnstile en mode géré pour un nombre illimité de requêtes. Si vous êtes un utilisateur de Cloudflare et vous souhaitez améliorer votre sécurité et votre expérience utilisateur pour vos points de terminaison d'API critiques, accédez à notre tableau de bord et créez dès aujourd'hui un widget Turnstile avec la fonction Pre-Clearance.

Nous protégeons des réseaux d'entreprise entiers, aidons nos clients à développer efficacement des applications à l'échelle d'Internet, accélérons tous les sites web ou applications Internet, repoussons les attaques DDoS, tenons les pirates informatiques à distance et pouvons vous accompagner dans votre parcours d'adoption de l'architecture Zero Trust.

Accédez à 1.1.1.1 depuis n'importe quel appareil pour commencer à utiliser notre application gratuite, qui rend votre navigation Internet plus rapide et plus sûre.

Pour en apprendre davantage sur notre mission, à savoir contribuer à bâtir un Internet meilleur, cliquez ici. Si vous cherchez de nouvelles perspectives professionnelles, consultez nos postes vacants.
SécuritéCAPTCHABots (FR)TurnstileNouveautés produitsDéveloppeursMicro-frontends

Suivre sur X

Adam Martinetti|@adamemcf
Benedikt Wolters|@worengawins
Miguel de Moura|@miguel_demoura
Cloudflare|@cloudflare

Publications associées

24 octobre 2024 à 13:00

Durable Objects aren't just durable, they're fast: a 10x speedup for Cloudflare Queues

Learn how we built Cloudflare Queues using our own Developer Platform and how it evolved to a geographically-distributed, horizontally-scalable architecture built on Durable Objects. Our new architecture supports over 10x more throughput and over 3x lower latency compared to the previous version....