Einen unbeabsichtigten öffentlichen Download schließen

CloudflareBeginner
Jetzt üben

Einführung

Ein privater Bucket kann trotzdem Dateien preisgeben, wenn ein öffentlicher Worker sie an jeden Aufrufer zurückgibt. Sie reproduzieren diesen Fehler mit zwei simulierten Exporten, fügen eine an den Leser gebundene Anwendungsautorisierung hinzu und weisen nach, dass private Downloads geschützt bleiben, während der öffentliche Health-Endpunkt weiterhin verfügbar ist.

Bearbeiten Sie zuerst die Lektionen zur Integration von Worker-Dokumenten und zu temporärem Zugriff. Diese frische VM stellt absichtlich einen unsicheren Handler, simulierte Dateien, Node.js 22.22.0, Wrangler 4.131.1 und Miniflare 4.20260730.0 bereit. Sie erstellen einen neuen privaten Bucket und einen kurzlebigen Worker. Aktives R2 sowie die entsprechenden Berechtigungen Ihres Lernkontos sind erforderlich. Lesen Sie dazu die Preisinformationen. Reale Dateien, echte Kundendaten oder eine benutzerdefinierte Domain werden nicht benötigt. Bereinigen Sie die offengelegte Demonstration und ihre Zugangsdaten, bevor Sie die Umgebung verlassen.

Den Anwendungs-Bucket verbinden

In diesem Schritt autorisieren Sie diese VM und erstellen einen unabhängigen privaten Bucket für die Anwendung. Die Geräteautorisierung bestätigt Ihr Lernkonto. Für die Verwaltung des R2-Buckets wird ein separates API-Token verwendet, das auf dieses Konto beschränkt ist.

Starten Sie Bash für die unten verwendete Befehlssyntax. Wechseln Sie anschließend in das vorbereitete Projekt und prüfen Sie die Werkzeuge. Lassen Sie dasselbe Terminal geöffnet, damit Ihre Variablen für die Ressourcennamen erhalten bleiben:

bash
cd /home/labex/project/r2-lab
export PATH="$PWD/.tools/node-v22.22.0-linux-x64/bin:$PATH"
node --version
npx wrangler --version

Autorisieren Sie den angezeigten Gerätecode in Ihrem eigenen Browser. Überprüfen Sie das Lernkonto sowie die angeforderten Lese-Bereiche für Konto und Benutzer, bevor Sie die Zustimmung erteilen:

npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_kv:write
npx wrangler whoami --json

Verlangen Sie loggedIn: true. Lesen Sie den Kontonamen auch dann ab, wenn nur ein Konto aufgelistet wird. Ersetzen Sie YOUR_ACCOUNT_ID unten durch die tatsächliche 32-stellige ID dieses Kontos. openssl rand -hex 6 erzeugt zwölf zufällige hexadezimale Zeichen, sodass dieses Lab nicht mit einem früheren Durchlauf kollidiert. Das Here-Dokument schreibt eine standardmäßige Konfigurationsdatei; die Shell setzt Ihre Variablen darin ein.

ACCOUNT_ID=YOUR_ACCOUNT_ID
RUN_ID=$(openssl rand -hex 6)
NAME="labex-c05-r08-$RUN_ID"
BUCKET="$NAME-docs"
cat > wrangler.jsonc <<JSON
{"name":"$NAME","account_id":"$ACCOUNT_ID","main":"src/index.js","workers_dev":true,"compatibility_date":"2026-07-30","r2_buckets":[{"binding":"DOCUMENTS","bucket_name":"$BUCKET"}]}
JSON

Öffnen Sie für die Bucket-Verwaltung die Seite API Tokens Ihres Cloudflare-Profils und erstellen Sie ein benutzerdefiniertes Token mit einem Namen, der diesem Lab entspricht. Erteilen Sie die Berechtigung Account → Workers R2 Storage → Edit und beschränken Sie Account Resources auf das Lernkonto, dessen ID Sie gespeichert haben. Legen Sie einen kurzen Ablaufzeitraum fest. Schließen Sie keine anderen Konten oder nicht benötigten Berechtigungen ein. Dieses Verwaltungstoken dient der Bucket-Verwaltung, einschließlich Erstellung und Löschung. In diesem Lab greift der Worker über sein DOCUMENTS-Binding auf R2-Objekte zu.

Kopieren Sie das Token einmal in die ausgeblendete Eingabeaufforderung dieser VM. umask 077 beschränkt den Dateizugriff auf Ihren Benutzer; read -s blendet die Eingabe aus. Die Datei verwendet Wranglers standardmäßige Token-Variable und wird von Git ausgeschlossen.

umask 077
read -r -s -p 'R2 management API token: ' R2_MANAGEMENT_TOKEN; printf '\n'
printf 'CLOUDFLARE_API_TOKEN=%s\n' "$R2_MANAGEMENT_TOKEN" > .env.management
unset R2_MANAGEMENT_TOKEN

Verwenden Sie --env-file=.env.management nur für R2-Verwaltungsbefehle. Der normale Befehl whoami prüft weiterhin die Geräteautorisierung der VM.

Setzen Sie --env-file an das Ende jedes Wrangler-Befehls, damit dessen Liste von Dateiargumenten nicht auch den Befehlsnamen erfasst. Wenn Wrangler nach dem Erstellen eines Buckets anbietet, eine Bindung zur Konfiguration hinzuzufügen, geben Sie n ein und drücken Sie die Eingabetaste. Die vorgesehene Bindung ist bereits konfiguriert.

npx wrangler r2 bucket create "$BUCKET" --env-file=.env.management

Listen Sie Ihre Buckets auf und suchen Sie den exakt generierten Namen. Andere Buckets gehören zu anderen Arbeiten; lassen Sie sie unverändert.

npx wrangler r2 bucket list --env-file=.env.management

Öffnen Sie im Dashboard Storage & databases → R2 → Overview, wählen Sie genau diesen Bucket aus und prüfen Sie die leere Objektliste. Lassen Sie in den Einstellungen die öffentliche Entwicklungs-URL und benutzerdefinierte Domains deaktiviert. Ein Bucket-Name im Dashboard bestätigt die Identität; die späteren Download-Prüfungen weisen nach, welche Bytes gespeichert wurden.

Die Berechtigung für Worker-Skripte ermöglicht die Bereitstellung. Die KV-Berechtigung unterstützt Wranglers Löschverwaltung; dieses Lab erstellt keinen KV-Namespace. Das R2-Verwaltungstoken bleibt eine separate, auf das Konto beschränkte Zugangsdaten.

Erstellen Sie zwei neue Anwendungszugangsdaten für die simulierten Leser. Dabei handelt es sich nicht um Cloudflare-API-Tokens. Legen Sie die beiden Objekte an und veröffentlichen Sie den bereitgestellten, absichtlich offengelegten Handler:

umask 077
printf "BLUE_TOKEN=%s\nGREEN_TOKEN=%s\n" "$(openssl rand -hex 24)" "$(openssl rand -hex 24)" > .dev.vars
npx wrangler r2 object put "$BUCKET/exports/blue/report.txt" --remote --file blue.txt --content-type text/plain --env-file=.env.management
npx wrangler r2 object put "$BUCKET/exports/green/report.txt" --remote --file green.txt --content-type text/plain --env-file=.env.management
npx wrangler deploy
npx wrangler secret bulk .dev.vars

Diese absichtlich offengelegte Bereitstellung enthält nur diese beiden simulierten Dateien. Verwenden Sie keine echten Exporte und lassen Sie den Worker nach der Übung nicht weiterlaufen.

Den unbeabsichtigten öffentlichen Download beobachten

In diesem Schritt reproduzieren Sie die Offenlegung über den Worker, während der zugrunde liegende Bucket privat bleibt. Ein Binding ermöglicht serverseitigem Code den Zugriff auf den Bucket. R2 entscheidet jedoch nicht automatisch, welchen HTTP-Aufrufern dieser Code vertrauen soll.

Kopieren Sie die exakte Bereitstellungs-URL und fordern Sie den blauen Export ohne Zugangsdaten an:

BASE_URL=https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev
curl -i "$BASE_URL/exports/blue/report.txt"

Verlangen Sie HTTP 200 und Synthetic blue export.. Wenn die neue Bereitstellung noch nicht überall verfügbar ist, wiederholen Sie die Abfrage bis zu einer Minute lang. Diese erfolgreiche anonyme Antwort ist der zu behebende Fehler.

Untersuchen Sie den bereitgestellten Handler:

cat src/index.js

Er liest einen R2-Schlüssel direkt aus der URL und gibt dessen Inhalt zurück, ohne zu prüfen, ob der Aufrufer Besitzer dieser Datei ist. Prüfen Sie im Dashboard die Bucket-Einstellungen: öffentliche Entwicklungs-URL deaktiviert und keine benutzerdefinierten Domains. Diese Einstellungen schließen die separate Worker-Route nicht. Führen Sie die Prüfung der Offenlegung aus, bevor Sie den Handler ersetzen.

Diese echten Einstellungen zeigen keine eigene Domain und eine deaktivierte öffentliche Entwicklungs-URL. Ein Worker mit R2-Bindung kann Daten weiterhin über seine eigene Route offenlegen.

Einstellungen des privaten Buckets

Diese echte Anfrage im VM-Terminal liefert ohne Zugangsdaten HTTP 200 und den synthetischen blauen Bericht. Benutzername, Ressourcenpräfix und Worker-URL sind Beispiele; verwende deine eigene Bereitstellungs-URL.

Anonymes HTTP 200 vor der Reparatur

Den Leser authentifizieren, bevor Sie den Schlüssel auswählen

In diesem Schritt verknüpfen Sie Authentifizierung (welcher Leser eine gültige Zugangsdaten besitzt) mit Autorisierung (welcher Leser dieses Objekt herunterladen darf). Ein gültiges blaues Token darf keinen grünen Export abrufen. Die authentifizierte Identität liefert den Besitzer des Schlüssels, und der Besitzer in der URL muss übereinstimmen, bevor R2 abgefragt wird.

Ersetzen Sie den Handler. Die beiden simulierten Zugangsdaten bilden die Leser dieses kleinen Beispiels ab. Eine echte Anwendung würde ihre Sitzung oder ihren Identitätsanbieter sowie autoritative Berechtigungsdatensätze verwenden. Akzeptieren Sie niemals einen vom Aufrufer übergebenen Namen als Identitätsnachweis.

cat > src/index.js <<'JS'
async function matches(actual, secret) {
  if (!secret) return false;
  const expected = `Bearer ${secret}`;
  const a = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(actual));
  const b = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(expected));
  return crypto.subtle.timingSafeEqual(a, b);
}
export default {
  async fetch(request, env) {
    const path = new URL(request.url).pathname;
    if (path === "/health" && request.method === "GET") return new Response("ok");
    const actual = request.headers.get("Authorization") || "";
    const owner = await matches(actual, env.BLUE_TOKEN) ? "blue" : await matches(actual, env.GREEN_TOKEN) ? "green" : null;
    if (!owner) return new Response("Unauthorized", { status: 401 });
    if (request.method !== "GET") return new Response("Method not allowed", { status: 405 });
    const route = /^\/exports\/(blue|green)\/([a-z0-9-]+\.txt)$/.exec(path);
    if (!route) return new Response("Not found", { status: 404 });
    if (route[1] !== owner) return new Response("Forbidden", { status: 403 });
    // The authenticated owner and validated path determine the storage key.
    const key = `exports/${owner}/${route[2]}`;
    const object = await env.DOCUMENTS.get(key);
    if (!object) return new Response("Not found", { status: 404 });
    const headers = new Headers({ "Cache-Control": "private, no-store" });
    object.writeHttpMetadata(headers);
    headers.set("ETag", object.httpEtag);
    return new Response(object.body, { headers });
  }
};
JS

Ein fehlendes Secret kann nicht versehentlich übereinstimmen. Der Digest-Vergleich verwendet die Timing-Safe-Gleichheitsoperation der Laufzeitumgebung. Der Health-Endpunkt bleibt außerhalb der geschützten Route, und private Antworten kommen nicht für einen gemeinsam genutzten Cache infrage. Ein Query-String-Parameter key kann den authentifizierten Speicherpfad nicht überschreiben.

Stellen Sie die Korrektur bereit:

npx wrangler deploy

Die Plattformprüfung führt zuerst einen separaten lokalen Lauf mit zufälligen simulierten Zugangsdaten und Objektinhalten aus. Eine erfolgreiche lokale Prüfung ist nützlich, bevor die bereitgestellte Korrektur bewertet wird.

Leserisolierung und erhaltenen Health-Zugriff nachweisen

In diesem Schritt testen Sie sowohl erlaubte als auch abgelehnte Pfade. Laden Sie die simulierten Zugangsdaten, ohne sie anzuzeigen, und laden Sie anschließend die Datei jedes Besitzers herunter:

set -a
source .dev.vars
set +a
curl -fsS -H "Authorization: Bearer $BLUE_TOKEN" "$BASE_URL/exports/blue/report.txt" -o blue-download.txt
cmp blue.txt blue-download.txt
curl -fsS -H "Authorization: Bearer $GREEN_TOKEN" "$BASE_URL/exports/green/report.txt" -o green-download.txt
cmp green.txt green-download.txt

Verlangen Sie eine bytegenaue Übereinstimmung. Testen Sie nun den anonymen Zugriff, einen Leser, der auf den Pfad des anderen Besitzers zugreift, einen fehlenden Schlüssel des eigenen Besitzers und den öffentlichen Health-Endpunkt:

curl -i "$BASE_URL/exports/blue/report.txt"
curl -i -H "Authorization: Bearer $BLUE_TOKEN" "$BASE_URL/exports/green/report.txt"
curl -i -H "Authorization: Bearer $BLUE_TOKEN" "$BASE_URL/exports/blue/missing.txt"
curl -i "$BASE_URL/health"

Verlangen Sie jeweils 401 Unauthorized, 403 Forbidden, 404 Not found und 200 ok. Status und Antwortinhalt müssen übereinstimmen. Die Plattformprüfung wiederholt die Leserisolierung remote und überprüft, dass das ausgewählte Konto Besitzer des Workers und seines privaten R2-Bindings ist.

Dieselbe Beispiel-URL liefert der anonymen Anfrage im VM-Terminal nun HTTP 401 Unauthorized. Dies sind HTTP-Ergebnisse im Terminal; authentifizierte Bytevergleiche und unabhängige Prüfungen belegen die Lesertrennung.

Anonymes HTTP 401 nach der Reparatur

Die Remote-Anwendung und den Bucket entfernen

In diesem Schritt löschen Sie nur den Worker und die Objekte dieses Labs, solange Sie noch autorisiert sind. Der private Bucket verschwindet nicht, wenn sein Worker gelöscht wird.

npx wrangler delete

Bestätigen Sie den exakt generierten Worker-Namen. Löschen Sie anschließend jedes hochgeladene Objekt ausdrücklich und danach den Bucket:

BUCKET=$(node -p "JSON.parse(require('fs').readFileSync('wrangler.jsonc')).r2_buckets[0].bucket_name")
npx wrangler r2 object delete "$BUCKET/exports/blue/report.txt" --remote --env-file=.env.management
npx wrangler r2 object delete "$BUCKET/exports/green/report.txt" --remote --env-file=.env.management
npx wrangler r2 bucket delete "$BUCKET" --env-file=.env.management

Es wurden nur die Schlüssel der blauen und grünen Berichte erstellt. Löschen Sie genau diese Schlüssel und lassen Sie nicht zu diesem Lab gehörende Kontoresourcen unverändert.

Aktualisieren Sie die Listen der Worker und Buckets im Dashboard und führen Sie die Plattformprüfung zur Bereinigung aus. Authentifizierungs- oder Netzwerkfehler sind nicht eindeutig und gelten nicht als erfolgreiche Löschung.

Verbleibende Zugangsdaten schließen

In diesem Schritt widerrufen Sie das Verwaltungstoken dieses Labs auf der Seite API Tokens Ihres Profils, entfernen das lokale Anwendungs-Secret und schließen die VM-Autorisierung. Führen Sie dies erst aus, wenn die vorherige Bereinigungsprüfung erfolgreich war.

rm .env.management .dev.vars
unset BLUE_TOKEN GREEN_TOKEN
npx wrangler logout
npx wrangler whoami --json || true

Verlangen Sie loggedIn: false. Der Widerruf des Verwaltungstokens ist ein separater manueller Prüfschritt im Dashboard; das Löschen der lokalen Datei allein widerruft das Token nicht. Lassen Sie die normale Dashboard-Anmeldung und die Tokens anderer Labs unverändert.

Zusammenfassung

Schließen Sie eine simulierte Dateifreigabe durch einen Worker, verknüpfen Sie die Identität des Lesers mit dem Besitz des Objekts, behalten Sie den Health-Zugriff bei und überprüfen Sie die Bereinigung des privaten Buckets.