Jetzt abonnieren, um Benachrichtigungen über neue Beiträge zu erhalten:

Integration von Turnstile in die Cloudflare-WAF schützt vor Fetch Requests

2023-12-18

Lesezeit: 4 Min.
Dieser Beitrag ist auch auf English, 繁體中文, Français, 日本語, 한국어, Português, Español, Polski, und 简体中文 verfügbar.

Cloudflare Turnstile ist seit zwei Monaten allgemein verfügbar. Damit steht Website-Betreibern auf der ganzen Welt nun eine einfache Option für die Bot-Abwehr zur Verfügung, die ganz ohne CAPTCHA auskommt. Mit Turnstile lässt sich per Code-Snippet unkompliziert eine Cloudflare-Challenge in eine Website einbetten. So wird sichergestellt, dass wirklich nur Datenverkehr passieren kann, der von einem Menschen generiert wurde. Turnstile schützt nicht nur das Frontend einer Website: Webadministratoren können darüber auch im Hintergrund laufende, browserinitiierte (AJAX)-API-Aufrufe absichern. Diese API werden häufig von dynamischen Single-Page-Webanwendungen verwendet, die beispielsweise mit React, Angular oder Vue.js erstellt wurden.

Integrating Turnstile with the Cloudflare WAF to challenge fetch requests

Wir geben heute bekannt, dass Turnstile in die Web Application Firewall (WAF) von Cloudflare integriert wurde. Damit können Webadministratoren ab sofort ein Turnstile-Code-Snippet in ihre Website einbinden und dann die Cloudflare-WAF zur Verwaltung dieser Anfragen konfigurieren. Mithilfe von WAF-Regeln lässt dieses Verfahren absolut individuell gestalteten. Sie können beispielsweise einem von Turnstile authentifizierten Nutzer erlauben, ohne weitere Challenges mit allen API-Endpunkten einer Applikation zu interagieren. Es ist auch möglich, bestimmte sensible Endpunkte wie den Login-Bereich so zu konfigurieren, dass dafür immer eine Challenge angezeigt wird.

Fetch Requests kommen in der Cloudflare-WAF auf den Prüfstand

Millionen von Websites, die durch die Cloudflare-WAF geschützt werden, nutzen die von uns angebotenen Lösungen JS Challenge, Managed Challenge und Interactive Challenge, um Bot-generierten Traffic aus dem Datenverkehr herauszufiltern. Bei jeder dieser Challenge-Kategorien fängt Cloudflare die entsprechende Anfrage ab und antwortet mit einer vom Browser gerenderten HTML-Seite. Auf dieser wird dem Nutzer eine einfache Aufgabe (die Challenge) gestellt. Löst er diese korrekt, weist er damit nach, dass er ein Mensch ist. Er erhält dann ein cf_clearance-Cookie. Dieses verrät Cloudflare, dass ein Nutzer eine Challenge gemeistert hat, um welche Art von Challenge es sich gehandelt hat und wann sie abgeschlossen wurde. Ein solches Freigabe-Cookie kann nicht zwischen Nutzern ausgetauscht werden und ist nur für den Zeitraum gültig, den der Cloudflare-Kunde unter „Security Settings“ (Sicherheitseinstellungen) festgelegt hat.

Dieses Verfahren funktioniert gut – es sei denn, ein Browser empfängt eine Challenge für eine Fetch Request und hat zuvor noch keine Challenge bestanden. Bei einer Fetch Request oder XMLhttpRequest (XHR) erwartet der Browser, dass einfacher Text (im JSON- oder XML-Format) zurückgegeben wird. Deshalb ist er nicht in der Lage, den zur Ausführung einer Challenge erforderlichen HTML-Code zu rendern.

Nehmen wir beispielsweise an, die Besitzerin einer Pizzeria hat in React ein Online-Bestellformular mit einer Zahlungsseite erstellt. Von dieser werden Daten an einen API-Endpunkt übermittelt, der Zahlungen verarbeitet. Ruft ein Nutzer das Webformular zur Eingabe seiner Kreditkartendaten auf, muss er eine Managed Challenge bestehen. Übermittelt er seine Kreditkartendaten dagegen per Fetch Request, führt der Browser den für die Durchführung der Challenge erforderlichen Code nicht aus. Der einzig mögliche Umgang der Pizzariabesitzerin mit verdächtigen Anfragen besteht darin, diese zu blockieren. Da davon aber auch legitime Anfragen betroffen sein können, ist ein solches Vorgehen unter Umständen geschäftsschädigend.

Hier kommt nun Turnstile ins Spiel. Denn damit lässt sich eine Cloudflare-Challenge in jedem beliebigen Bereich einer Website einbetten. Bisher war Turnstile nur in der Lage, ein Einmal-Token auszugeben. Um Kunden Challenges für diese Fetch Requests zu ermöglichen, kann Turnstile nun aber ein Freigabe-Cookie für die Domain ausgeben, bei der der Dienst eingebettet ist. Kunden können ihre Challenge auf der HTML-Seite vor einem Fetch Request ausspielen und so eine Vorabfreigabe des Besuchers für die Interaktion mit der Zahlungs-API vornehmen lassen.

Vorabfreigabemodus von Turnstile

Zurück zu unserem Pizzeria-Beispiel: Eine solche Vorabfreigabe für die Integration von Turnstile in die Cloudflare-WAF bietet drei große Vorteile:

  1. Bessere Nutzererfahrung: Die eingebettete Challenge von Turnstile kann im Hintergrund ausgeführt werden, während der Besucher seine Zahlungsdaten eingibt.

  2. Abwehr einer größeren Zahl von Anfragen an der Edge: Turnstile gibt jetzt ein Freigabe-Cookie für die Domain aus, in die der Dienst eingebettet ist. Damit kann unsere Pizzeriabesitzerin mithilfe einer benutzerdefinierten Regel für jede Anfrage an die Zahlungs-API eine Managed Challenge anzeigen lassen. So ist Cloudflare in der Lage, direkt auf die Zahlungs-API abzielende automatisierte Angriffe zu stoppen, bevor sie diese erreichen.

  3. (Optional) Absicherung der Aktion und des Nutzers: Um sich die Vorabfreigabe zunutze zu machen, sind keine Anpassungen am Backend-Quellcode erforderlich. Eine stärkere Integration von Turnstile erhöht aber die Sicherheit der eingebundenen API. Die Pizzeriabesitzerin kann ihr Zahlungsformular so anpassen, dass der erhaltene Turnstile-Token validiert wird. So wird die individuelle Validierung jedes Zahlungsversuchs durch Turnstile sichergestellt, wodurch der Zahlungsendpunkt vor Session Hijacking (Kapern einer Sitzung) geschützt ist.

Ein Turnstile-Widget mit aktivierter Vorabfreigabe (Pre-Clearance) stellt weiterhin Turnstile-Token aus. Deshalb können die Kunden selbst entscheiden, ob ein Endpunkt so wichtig ist, dass jede Anfrage einer gesonderten Sicherheitsüberprüfung unterzogen werden muss. Andernfalls erfolgt diese nur einmal pro Sitzung. Von einem Turnstile-Widget generierte Freigabe-Cookies werden automatisch auf die Cloudflare-Zone angewandt, in die das Turnstile-Widget eingebettet ist – eine Konfiguration ist dafür nicht erforderlich. Die Gültigkeitsdauer des Token wird weiterhin durch die zonenspezifische „Challenge-Passage“ (Challenge Zeitfenster)-Zeit gesteuert.

Turnstile mit Vorabfreigabe implementieren

Um das Ganze zu konkretisieren, schauen wir uns als Nächstes eine einfache Implementierung an. Wir haben eine einfache Demo-Applikation eingerichtet, in der ein Frontend emuliert wird, das mit einem Backend auf einem /your-api-Endpunkt kommuniziert.

Dazu wurde der folgende Quellcode verwendet:

Wir haben eine Schaltfläche erstellt. Wird diese angeklickt, stellt Cloudflare eine fetch()-Anfrage an den /your-api-Endpunkt. Das Ergebnis wird im Antwort-Container angezeigt.

<!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>

Nehmen wir nun an, dass eine Cloudflare-WAF-Regel eingerichtet wurde, die den /your-api-Endpunkt mit einer Managed Challenge schützt.

Diese Regel hat zur Folge, dass die gerade beschriebene Anwendung aus dem zuvor erläuterten Grund (der Browser erwartet eine JSON-Antwort, empfängt aber stattdessen die Challenge-Seite als HTML) mit ihrer Anfrage scheitert.

Unter der Registerkarte „Network“ (Netzwerk) ist zu sehen, dass auf die Anfrage an /your-api die Fehlermeldung 403 ausgegeben wurde.

Bei näherer Betrachtung zeigt der Cf-Mitigated-Header, dass die Antwort von der Cloudflare-Firewall einer Challenge unterzogen wurde, da der Besucher bisher noch keine Challenge gelöst hat.

Um dieses Problem in unserer Anwendung zu beheben, haben wir für den Turnstile-Website-Schlüssel (sitekey), den wir verwenden möchten, ein Turnstile-Widget im Vorabfreigabe-Modus eingerichtet.

In unserer Anwendung überschreiben wir die Funktion fetch(), damit Turnstile aufgerufen wird, sobald eine Cf-Mitigated-Antwort empfangen wurde.

Das obenstehende Snippet enthält so einiges: Zuerst erstellen wir ein verstecktes überlagerndes Element (Overlay) und überschreiben die fetch()-Funktion des Browsers. Die fetch()-Funktion wird so geändert, dass der Cf-Mitigated-Header auf das Vorhandensein von „challenge“ hin überprüft wird. Wird eine Challenge ausgegeben, ist das erste Ergebnis negativ. Stattdessen wird in unserer Webanwendung ein Turnstile-Overlay (mit aktivierter Vorabfreigabe) angezeigt. Wenn die Turnstile-Challenge erfolgreich absolviert wurde, versuchen wir es erneut mit der vorherigen Anfrage, nachdem Turnstile das cf_clearance-Cookie erhalten hat, um die Cloudflare-WAF passieren zu können.

<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>

Wurde das Turnstile-Widgets ordnungsgemäß beantwortet, verschwindet das Overlay und das angeforderte API-Ergebnis wird angezeigt:

Vorabfreigabe-Funktion für alle Cloudflare-Kunden verfügbar

Jeder Cloudflare-Nutzer – gleichgültig, ob er unserer kostenloses Angebot oder eine Bezahloption verwendet – kann Turnstile im verwalteten Modus für eine unbegrenzte Anzahl von Anfragen geführenfrei einsetzen. Wenn Sie Cloudflare-User sind und für Ihre kritischen API-Endpunkte das Sicherheitsniveau erhöhen und die Nutzererfahrung verbessern möchten, können Sie in unserem Dashboard ein Turnstile-Widget mit Vorabfreigabe (Pre-Clearance) erstellen.

Wir schützen komplette Firmennetzwerke, helfen Kunden dabei, Internetanwendungen effizient zu erstellen, jede Website oder Internetanwendung zu beschleunigen, DDoS-Angriffe abzuwehren, Hacker in Schach zu halten, und unterstützen Sie bei Ihrer Umstellung auf Zero Trust.

Greifen Sie von einem beliebigen Gerät auf 1.1.1.1 zu und nutzen Sie unsere kostenlose App, die Ihr Internet schneller und sicherer macht.

Wenn Sie mehr über unsere Mission, das Internet besser zu machen, erfahren möchten, beginnen Sie hier. Sie möchten sich beruflich neu orientieren? Dann werfen Sie doch einen Blick auf unsere offenen Stellen.
SicherheitCAPTCHABots (DE)TurnstileProdukt-NewsEntwicklerMicro-frontends

Folgen auf X

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

Verwandte Beiträge

24. Oktober 2024 um 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....