Fetch-Metadaten
Fetch-Metadaten ist der Begriff für eine Gruppe von HTTP-Anforderungs-Headern, die dem Server Informationen über den Kontext geben, in dem die Anforderung gestellt wird.
Fetch-Metadaten ermöglichen es dem Server unter anderem zu wissen:
-
Ob die Anforderung eine Navigation zwischen Dokumenten darstellt, eine Anforderung für eine Subressource ist oder ausdrücklich von JavaScript erstellt wurde, zum Beispiel mit der
fetch()-API. -
Die Beziehung zwischen dem Anforderer der Ressource und der angeforderten Ressource: ob sie vom gleichen origin oder vom gleichen site stammen oder von völlig unterschiedlichen Seiten.
Indem der Server die Informationen in diesen Headern nutzt, um spezifische Anfragen zuzulassen oder abzulehnen, kann er eine Verteidigung gegen cross-origin Angriffe wie Cross-Site Request Forgeries (CSRF) und verschiedene Cross-Site Leaks implementieren.
Fetch-Metadaten-Header
Die Fetch-Metadaten-Spezifikation definiert vier Fetch-Metadaten-Header:
Wie alle mit Sec- präfixierten Header sind dies verbotene Anforderungs-Header, was bedeutet, dass sie vom Frontend-Code der Website nicht gesetzt oder modifiziert werden können.
Sec-Fetch-Dest
Dieser Header gibt das Ziel der Anforderung an. Dieses Attribut ist in der Fetch-API definiert, wo es als Request.destination-Eigenschaft zugänglich ist.
Man könnte ihn ungefähr so ansehen, wie die zurückgegebene Ressource verwendet werden würde.
Bei den meisten ersetzten Elementen benennt der Wert des Headers das Element, für das diese Ressource verwendet wird, wie iframe, object, audio oder video. Ein Wert von image gibt an, dass die Ressource als Bild verwendet wird, das von einem ersetzten Element wie einem HTML-<img>-Element, einer CSS-background-image-Eigenschaft, einem SVG-<image> oder an einer anderen Stelle in der Web-Plattform, die Bilder aus Subressourcen nutzt, referenziert wird.
Weitere interessante Zielwerte sind:
document-
Die Anforderung gilt für ein neues Dokument, das das Ziel einer Top-Level-Navigation ist (zum Beispiel, wenn der Benutzer auf einen Link auf der Seite klickt oder ein Formular absendet).
script-
Die Ressource wird als Skript geladen, das von einem HTML-
<script>-Element oder einem Aufruf vonimportScripts()in einem Web-Worker geladen wird.Spezifischere Werte werden verwendet, um andere Orte anzuzeigen, an denen die Ressource als Skript verwendet wird, wie Worklets (
audioworkletundpaintworklet) und Worker (sharedworker,serviceworkerundworker). empty-
Die Anforderung hat kein definiertes Ziel: unter anderen möglichen Ursachen ist dies der Wert, der gegeben wird, wenn die Anforderung das Ergebnis eines
fetch()-Aufrufs ist.
Für die vollständige Liste möglicher Werte siehe die Referenzseite für diesen Header.
Sec-Fetch-Mode
Dieser Header gibt den Modus der Anforderung an. Wie beim Ziel ist der Modus in der Fetch-API definiert, wo er als Request.mode-Eigenschaft zugänglich ist.
Die am häufigsten genutzten Werte sind:
-
Die Anforderung stellt eine Navigation zwischen Dokumenten dar (zum Beispiel, wenn der Benutzer auf einen Link klickt).
no-cors-
Die Anforderung wurde im
no-cors-Modus gestellt.Das bedeutet, dass sie ohne die richtigen CORS-Header serverseitig erlaubt ist Cross-Origin, mit der Einschränkung, dass die Antwort nicht von JavaScript im Client abgerufen werden kann (sie ist undurchsichtig).
Dies ist der Standardmodus für Seiten, die Subressourcen wie Bilder, Schriften, Skripte und Stylesheets laden, und erklärt, warum eine andere Seite standardmäßig Ihre Subressourcen verwenden darf, auch wenn Sie CORS nicht konfiguriert haben, um dies zu erlauben.
cors-
Wenn die Anforderung Cross-Origin ist, muss der Server mit den richtigen CORS-Headern antworten, oder die Anforderung wird fehlschlagen. Wenn der Server mit den richtigen CORS-Headern antwortet, werden der Antwortkörper und bestimmte Header dem Anforderer zur Verfügung gestellt.
Dies findet sich am häufigsten bei Cross-Origin-Anfragen, die über JavaScript unter Verwendung der Fetch-API gestellt werden, wenn der Anforderer Zugriff auf die zurückgegebene Ressource benötigt (zum Beispiel ein Fetch-Aufruf, um JSON vom Server abzurufen).
same-origin-
Die Anforderung ist nur erlaubt, wenn der Anforderer gleichen Ursprung mit der angeforderten Ressource hat.
Sec-Fetch-Site
Dieser Header zeigt die Beziehung zwischen dem Ursprung der angeforderten Ressource und dem Ursprung des Anforderers der Ressource an.
Er zeigt an, ob der Anforderer von:
- Dem gleichen origin wie die angeforderte Ressource stammt.
- Einem anderen Ursprung, aber der gleichen site.
- Einer anderen site.
Zum Beispiel, wenn ein Benutzer auf einen Link in einer Seite unter https://books.example.org/authors klickt, erstellt der Browser eine Anfrage, um das im Linkziel angegebene Dokument abzurufen. Die folgende Tabelle zeigt die Werte des zugehörigen Sec-Fetch-Site-Headers für verschiedene Linkzielwerte:
| Linkziel | Sec-Fetch-Site-Wert |
|---|---|
https://books.example.org/titles |
same-origin |
https://login.example.org/ |
same-site |
https://books.example.com/titles |
cross-site |
Ähnliche Abbildungen gelten für andere HTTP-Anfragen, wie:
- Formularübermittlungen über das
action-Attribut eines<form>-Elements. - Anfragen für Subressourcen wie Bilder, Schriften oder Skripte.
- Anfragen, die mit der
fetch()-API gestellt werden.
Der Sec-Fetch-Site-Header kann auch den Wert none für Anfragen haben, die keine site als Anforderer haben, einschließlich zum Beispiel Anfragen, die gemacht werden, wenn der Benutzer eine URL in die Adressleiste des Browsers eingibt oder ein Lesezeichen anklickt. Die Spezifikation nennt diese direkt durch den Benutzer initiierte Anforderungen.
Sec-Fetch-User
Dieser Header wird nur hinzugefügt, wenn die Anforderung durch eine Benutzeraktion (wie ein Klick auf einen Link) initiiert wurde, und wenn er hinzugefügt wird, hat er immer den Wert ?1.
Cross-Origin-Angriffe
Fetch-Metadaten sind besonders nützlich als Verteidigung gegen Cross-Origin-Angriffe. Diese Angriffe zielen typischerweise auf einen Benutzer ab, der ein Konto bei einer legitimen Website hat und bei dieser angemeldet ist. Der Angreifer erstellt eine Website, die eine Cross-Origin-Anfrage an die legitime Website stellt und dann den Benutzer dazu verleitet, diese Anfrage auszuführen.
Hinweis: Wir verwenden den Begriff Cross-Origin-Angriff in diesem Leitfaden, obwohl viele Angriffe traditionell Cross-Site-Angriffe genannt werden.
Ein origin ist ein restriktiveres Konzept als eine site. Insbesondere umfasst eine site auch die Subdomains einer Domain, ein origin jedoch nicht: so sind https://example.org und https://login.example.org die gleiche site, aber unterschiedliche origins.
Das bedeutet, dass, während alle Cross-Site-Angriffe Cross-Origin-Angriffe sind, einige Cross-Origin-Angriffe keine Cross-Site-Angriffe sind. Wenn ein Angreifer beispielsweise die Kontrolle über eine Subdomain einer site erlangt, kann er die site mit Cross-Origin, same-site-Anfragen angreifen. Um diese Angriffe einzuschließen, verwenden wir den restriktiveren Begriff.
Zum Beispiel könnte die Seite des Angreifers ein <form>-Element enthalten, das an die legitime Seite gesendet wird. Für einige Cross-Origin-Angriffe ist keine Benutzerinteraktion erforderlich: Die Seite des Angreifers kann einfach eine fetch()-Anfrage an die legitime Seite beim Page-Load ausführen, und der Benutzer muss nur die Seite des Angreifers öffnen, damit die Cross-Origin-Anfrage ausgeführt wird.
Da die Anfrage vom Browser des Benutzers stammt, wird sie alle Cookies enthalten, die für den Benutzer von der legitimen Seite gesetzt wurden, einschließlich der Cookies, die die legitime Seite zur Identifizierung von Benutzern verwendet. Die Anfrage wird daher mit den Berechtigungen für diesen Benutzer akzeptiert.
Wir können zwei Arten von Cross-Origin-Angriffen unterscheiden:
-
Cross-Site Request Forgery (CSRF)-Angriffe: Bei diesen Angriffen führt die Cross-Origin-Anfrage eine relevante Aktion auf dem legitimen Server aus, wobei Parameter verwendet werden, die vom Angreifer bereitgestellt werden. Zum Beispiel fordert die Anfrage den Server auf, Geld vom Konto des Zielbenutzers auf das des Angreifers zu überweisen.
-
Cross-Site Leaks: Bei diesen Angriffen verwendet der Angreifer die Anfrage, um Informationen über die Beziehung des Benutzers zu der Zielseite zu erlangen, oft über Seitenkanäle wie Fehlerereignisse.
Die meisten Websites möchten einige Cross-Origin-Anfragen ablehnen, während sie andere zulassen: Wenn Sie zum Beispiel alle Cross-Origin-Anfragen ablehnen, wird niemand in der Lage sein, von einer anderen Seite auf Ihre Seite zu navigieren!
Unter Verwendung von Fetch-Metadaten kann ein Server eine Richtlinie erstellen, um Cross-Origin-Anfragen basierend auf den Detailinformationen über ihren Kontext zuzulassen oder abzulehnen.
Richtlinie zur Ressourcenisolation
Eine häufige Art von Richtlinie wird als Ressourcenisolationsrichtlinie bezeichnet. Wenn der Server eine Anfrage erhält, untersucht er die Anfragen-Metadaten-Header, um nur Folgendes zuzulassen:
- Same-Origin-Anfragen (und manchmal same-site-Anfragen, wenn Sie Ihren Subdomains vertrauen).
- Top-Level-Navigationsanforderungen von einem anderen Ursprung, sodass Benutzer Ihre Seite durch Klicken von Links auf anderen Seiten erreichen können.
- Anfragen zu bestimmten Endpunkten, die Cross-Origin aufgerufen werden sollen, einschließlich solcher, die CORS verwenden.
Das folgende Express-Beispiel erlaubt nur Same-Origin-Anfragen, direkt vom Benutzer initiierte Anfragen und Navigationen.
function isAllowed(req) {
// Allow same-origin requests
// Allow directly user-initiated requests (from bookmarks, address bar etc.)
const secFetchSite = req.headers["sec-fetch-site"];
if (secFetchSite === "same-origin" || secFetchSite === "none") {
return true;
}
// Allow cross-site navigations, such as clicking links
const secFetchMode = req.headers["sec-fetch-mode"];
if (secFetchMode === "navigate" && req.method === "GET") {
return true;
}
// Deny everything else
return false;
}
app.get("/admin", (req, res) => {
res.setHeader("Vary", "sec-fetch-site, sec-fetch-mode");
if (isAllowed(req)) {
// Respond with the admin page if the user is admin
getAdminPage(req, res);
} else {
res.status(403).send("Forbidden");
}
});
Es sendet außerdem den Vary-Antwort-Header. Dies stellt sicher, dass, wenn die Antwort zwischengespeichert wird, die zwischengespeicherte Antwort nur für Anfragen mit den gleichen Werten für die von uns verwendeten Fetch-Metadaten-Header bereitgestellt wird.
Die Resource Isolation Policy-Seite bietet weiteren Beispielcode für eine Ressourcenisolationsrichtlinie.
Siehe auch
- CSRF
- Cross-Site Leaks
- Schützen Sie Ihre Ressourcen vor Web-Angriffen mit Fetch-Metadaten (web.dev)
- Fetch Metadata (XS-Leaks Wiki)