Das war's wohl für NextJS... 13 NEUE Sicherheitslücken

BBetter Stack
Computing/SoftwareBusiness NewsInternet Technology

Transcript

00:00:00Es ist wieder passiert. Das ist bereits mein drittes Video zu Server-Component-CVEs in diesem Jahr,
00:00:05und ich glaube nicht mal, dass ich alle abgedeckt habe. Diesmal sind es 13 CVEs bei React
00:00:11und Next.js – ja, 13 Stück –, wovon 6 als hochriskant eingestuft sind, darunter Denial-of-Service,
00:00:15Middleware-Bypasses, Cross-Site Scripting und mehr. Vielleicht waren Server Components ein Fehler.
00:00:20Hier ist das Next.js-Sicherheits-Release, in dem nur ein paar „beiläufige“ Probleme behoben werden,
00:00:28die sie diesen Monat hatten. Ganz unten steht natürlich die Lösung: Aktualisiert
00:00:32alle eure Next.js-Versionen. Das hier sind die betroffenen Versionen. Es ist erwähnenswert,
00:00:36dass TanStack davon nicht betroffen ist. Ich bin vielleicht voreingenommen, aber das ist ein weiterer Grund,
00:00:41warum ich TanStack nutze. Ich werde jetzt nicht alle durchgehen, sonst säßen wir ewig hier,
00:00:44und ich habe auch noch nicht für alle funktionierende Exploits gefunden. Aber ich möchte euch
00:00:48einen aus jeder Kategorie zeigen. Wir beginnen mit einem Middleware- und Proxy-Bypass,
00:00:52und den, den ich nachstellen konnte, ist dieser hier beim Pages Router. Wir haben also einen
00:00:56Middleware-Proxy-Bypass im Pages Router bei Verwendung von i18n. Dieser CVE hat einen Schweregrad
00:01:02von 7,5 von 10. Dies ist ein Beispiel für eine verwundbare Anwendung: In der Next.js-Konfiguration
00:01:06habe ich i18n aktiviert und zwei Locales eingerichtet: Englisch und Französisch. Zudem gibt es eine Middleware-Datei,
00:01:12die in neueren Next.js-Versionen in „proxy“ umbenannt wurde, um die Verwirrung zu vermeiden,
00:01:16die ich gleich zeige. Im Grunde sollte uns Middleware erlauben,
00:01:19eingehende Anfragen zu modifizieren, sei es durch Weiterleitung, Rewriting oder das Hinzufügen
00:01:24von Headern. In meinem Fall prüfe ich beim Versuch, die „/secret“-Seite aufzurufen,
00:01:28ob ein Session-Cookie vorhanden ist, der Nutzer also eingeloggt ist. Falls nicht,
00:01:32sollte die Weiterleitung zur Login-Seite erfolgen, damit nur autorisierte Nutzer mein Geheimnis sehen.
00:01:37Unten haben wir einen Matcher, damit die Middleware für die Geheimseite auch
00:01:41die lokalen Varianten erfasst, da wir durch die zwei Locales technisch gesehen drei Versionen der URL haben.
00:01:45Auf der Geheimseite selbst nutze ich Server-Side Props; diese sollten zum Rendering-Zeitpunkt
00:01:50vom Server abgerufen werden. Wegen der Middleware sollte theoretisch nur ein angemeldeter Nutzer
00:01:54diese Werte sehen können. Diese nutze ich später auf der Seite selbst: eine E-Mail, ein Flag
00:01:58und eine Überschrift. Nur ein autorisierter Nutzer sollte das sehen können. Testen wir das mal.
00:02:03Zuerst versuche ich, die Geheimseite aufzurufen. Wie man sieht, werde ich zum Login weitergeleitet,
00:02:07da ich nicht eingeloggt bin. Die Middleware funktioniert also. Aber was, wenn wir zu Meister-Hackern werden?
00:02:11Das können wir tun, indem wir zuerst das Element untersuchen – absolut krasses Hacker-Zeug.
00:02:16Im „next-data“-Skript hier unten müssen wir nach unserer Build-ID suchen. In meinem Fall
00:02:20ist es diese hier. Wir kopieren sie und müssen dann eine URL eingeben,
00:02:24die so aussieht: _next/data/ [Build-ID] / [Seite].json.
00:02:28Wenn man das macht, sieht man, dass wir die Props zurückbekommen, die eigentlich durch die
00:02:32Middleware geschützt sein sollten. In meinem Fall waren das Flag, E-Mail, Überschrift und der Hinweis,
00:02:37für mehr Entwickler-News und Tipps zu abonnieren. Also tut das bitte! Ich hoffe, ich habe euch
00:02:40mit meinen Hacker-Skills beeindruckt. Aber warum passiert das eigentlich? Nun, das ist
00:02:44so einfach zu erklären wie es durchzuführen war. Wir hatten unsere Geheimseite mit Server-Side Props.
00:02:48In Next.js werden diese Props über eine URL wie diese hier ausgeliefert. Unsere Middleware
00:02:52hätte diese Route schützen müssen. Das Problem: Da wir i18n nutzten, hatten wir
00:02:56auch zwei andere URLs, die englische und die französische Variante. Man sieht,
00:03:00dass auch die Server-Side Props englische und französische Varianten erhalten. Next.js hatte
00:03:05einfach fehlerhaften Code: Wenn i18n aktiviert war, wurde der Basisfall nicht geschützt.
00:03:09Dieser war nicht im Matcher enthalten, die englische und französische Version hingegen schon.
00:03:13Die Varianten waren geschützt, aber nicht der Basisfall „/secret“. Das sieht man sofort,
00:03:18wenn ich die URL zur englischen Version ändere: Ich werde zum Login weitergeleitet. Eine unglaublich
00:03:22einfache Sicherheitslücke. Aber ehrlich gesagt klingen diese Middleware-Bypasses oft schlimmer,
00:03:26als sie sind. Sie sind nicht gut, aber man sollte ohnehin nicht zu viel allein mit Middleware schützen.
00:03:31Next.js empfiehlt das auch gar nicht. Wenn ihr sensible Daten in Server-Side Props habt
00:03:35und keine Server-Auth-Logik nutzt, liegt ein Teil der Schuld auch bei euch. Kommen wir zu etwas
00:03:40Schwerwiegenderem: Denial-of-Service. Es gab drei davon, aber ich konnte nur einen
00:03:44zuverlässig rekonstruieren. Das war dieser hier: Denial-of-Service mit Server Components.
00:03:48Das betrifft Next.js sowie alles, was das „react-server-dom“-Paket nutzt – also fast nur Next.js
00:03:53und Frameworks, die es kopiert haben. TanStack Start nutzt das nicht und ist daher nicht anfällig.
00:03:56Die Schwere liegt auch hier bei 7,5 von 10. Für diesen Exploit reicht eine einfache Next.js-App,
00:04:01die eine Server Action verwendet. Hier läuft die Seite gerade, und wie man beim Refresh sieht,
00:04:05lädt sie fast sofort. Um das in Zahlen zu fassen: Wenn ich diese Anfrage sende,
00:04:10dauert es 0,02 Sekunden. Wenn ich nun meinen Exploit starte und die Anfrage erneut sende,
00:04:14dauert es sechs Sekunden. Und das war nur ein einziger Exploit-Durchlauf – stellt euch vor,
00:04:18ich würde sie verketten. Um den Exploit zu verstehen, muss man das React-Flight-Protokoll kennen.
00:04:22Das ist das Format, mit dem React Komponentenbäume und Daten zwischen Server und Client serialisiert.
00:04:25Ihr habt das wahrscheinlich schon mal gesehen: Auf dieser Seite hatten wir ein Formular mit einer Server Action.
00:04:29Im Network-Tab sieht man, dass der Payload als Daten gesendet wird, die wie Kauderwelsch aussehen.
00:04:34Dasselbe gilt für die Antwort. Wenn wir diesen Payload kopieren, kann ich erklären,
00:04:39was auf dem Server passiert. Der erste Schritt ist die Deserialisierung. Sie beginnt bei Chunk 0,
00:04:42wo wir dieses „$k1“ haben. Das ist ein Pointer, der besagt, dass hier Formular-Daten folgen,
00:04:46die mit einem Unterstrich beginnen. Er nimmt also alle anderen Keys des Payloads,
00:04:50geht sie durch und sucht nach einem String, der mit einem Unterstrich beginnt, um Key und Value zu finden.
00:04:54Danach kann er Name, E-Mail und Nachricht zuordnen und die Daten in dieses Objekt hier unten umwandeln.
00:04:58Schön einfach. Das Problem bei diesem Ansatz zeigt sich aber bei der Skalierung.
00:05:02Sagen wir, ich füge einen weiteren Pointer „$k2“ hinzu, der nach Keys sucht, die mit zwei Unterstrichen beginnen.
00:05:05Nun passiert folgendes: Bei „$k1“ werden alle sechs Keys nach einem Unterstrich durchsucht.
00:05:10Bei „$k2“ passiert genau dasselbe für zwei Unterstriche. Wir prüfen also insgesamt 12 Keys.
00:05:16Das ist noch okay, aber treiben wir es auf die Spitze. Wenn wir 199.999 zufällige Keys
00:05:20in den Payload packen und unser Array bei Index Null von „$k1“, „$k2“ bis zu „$k1000“ ändern,
00:05:24muss für jeden dieser 1000 Pointer die Liste der 200.000 Keys durchsucht werden.
00:05:28Das ergibt insgesamt 200 Millionen String-Vergleiche. Wie man sich denken kann,
00:05:32blockiert das den Thread für einige Sekunden. Hier ist der Commit, der das Problem behoben hat.
00:05:36Er ist ziemlich komplex, aber ich versuche es so gut wie möglich zu erklären. Im Grunde
00:05:41nutzen sie jetzt ein Cursor-basiertes System. Alle 200.000 Keys werden in eine Liste geladen,
00:05:44und bei der Suche nach „$k1“ wandert ein Cursor die Liste herab, der nicht mehr zurückgehen kann.
00:05:48Er prüft „$j1“ – kein Match –, dann „$j2“ und so weiter bis ganz nach unten zu „$j199.999“.
00:05:52Wenn dort kein Treffer für „$k1“ gefunden wurde, wird mit „$k2“ fortgefahren. Aber da der Cursor
00:05:56bereits am Ende der Liste steht und nicht zurückgehen kann, ist „$k2“ sofort „undefined“.
00:06:03Das setzt sich bis „$k1000“ fort. Diesmal sind wir also insgesamt nur einmal über die 200.000 Keys gegangen.
00:06:07Dieser Fix reduziert die Operationen von k * n (Anzahl Pointer mal Keys) auf n + k.
00:06:12In unserem Beispiel von 200 Millionen auf 201.000 Operationen. Dieser Tweet von Prime
00:06:17trifft den Nagel auf den Kopf: Ein eigenes Protokoll mit Serialisierung zu bauen, ist extrem schwer.
00:06:21Daher überraschen diese Probleme nicht. Meiner Meinung nach sollten sie Claude Mythos mal
00:06:25über den React- und Next.js-Code schauen lassen. Als Nächstes haben wir den CVE mit der höchsten Schwere:
00:06:28Server-Side Request Forgery (SSRF) in Next.js-Anwendungen. Dieser liegt bei 8,6 von 10.
00:06:33Wichtig: Vercel-Deployments waren nicht betroffen, nur Self-Hosted oder andere Provider.
00:06:36Sie laden also alle diese 200.000 Schlüssel, die wir in unserem Payload gesendet haben, in eine Liste und dann
00:06:41beginnen wir hier bei Null, wo nach der $k1-Referenz gesucht wird, und es geht
00:06:45diese Liste mit einem Cursor nach unten, der nicht zurückgehen kann. Es geht also hier runter zu $j1, sieht, dass das
00:06:50nicht mit dem benötigten Unterstrich übereinstimmt, also geht es zu $j2, was auch nicht
00:06:54mit dem Unterstrich übereinstimmt, also geht es die ganze Liste weiter runter bis zu $j199.999. Sobald es
00:07:01hier angekommen ist, merkt es, dass es keine Übereinstimmung für $k1 gibt, also geht es weiter zu $k2. Nun sucht $k2
00:07:06nach dem zweiten Unterstrich, aber das Problem ist, da dies ein cursorbasiertes System ist und dieser Cursor
00:07:09nicht zurückgehen kann, läuft er sofort am Ende der Liste aus, sodass dies auch
00:07:14nicht definiert sein wird, und das setzt sich bis zu $k1000 fort. Dieses Mal sind wir also nur
00:07:18über 200.000 Schlüssel gegangen. Im Grunde hat dieser Fix die Anzahl der Operationen von
00:07:23$k*n, wobei $k die Anzahl der $k-Referenzen und $n die Anzahl der Schlüssel ist, gesenkt
00:07:27auf $n+k. In unserem Fall gingen wir von 200.000.000 Operationen runter auf 201.000, da
00:07:33es immer noch alle Schlüssel und auch diese $k-Referenzen durchgehen muss. Ich finde,
00:07:37dieser Tweet von Prime fasst die Situation, in der wir uns befinden, wirklich gut zusammen. Ein eigenes Protokoll mit Serialisierung
00:07:41zu erstellen, ist unglaublich schwer, daher überrascht es nicht, dass wir so viele Probleme sehen. Meiner Meinung nach
00:07:46sollten sie Claude Mythos mal über die React- und Next.js-Codebase schauen lassen. Als
00:07:50nächstes haben wir die schwerwiegendste CVE von allen, nämlich Server-Side Request Forgery in
00:07:54Next.js-Anwendungen. Wie man sieht, ist diese mit 8,6 von 10 eingestuft, aber es ist auch
00:07:59erwähnenswert, dass dies keine Vercel-gehosteten Deployments betraf, sondern nur Self-Hosted oder andere Anbieter.
00:08:04Dieser Exploit ist zudem super einfach auszunutzen. Zuerst müssen wir unseren Next.js-Server starten,
00:08:09und auch hier kann es eine Standard-Next.js-Anwendung sein. Man muss keine Änderungen vornehmen.
00:08:14Als Nächstes brauchen wir auch einen internen Server. Nehmen wir an, dieser Server könnte nur vom
00:08:18Next.js-Server und nicht von der Außenwelt erreicht werden. Sagen wir, er befände sich in unserem Cloud-Deployment.
00:08:23Dann senden wir einfach eine sehr simple Curl-Anfrage, wobei wir eine
00:08:26Curl-Anfrage an unsere Next.js-Anwendung schicken. Das war auf Port 3002, und wir sagen, dass unser
00:08:31einzutauchen. Lasst mich wissen, ob ihr noch dabei seid, indem ihr etwas Beliebiges kommentiert,
00:08:36vielleicht „Bar“ oder so, und abonniert, wenn euch der Content gefällt. Zwei Kategorien fehlen noch,
00:08:40aber die gehen schneller. Zuerst Cache Poisoning; hier konnte ich dieses moderate Problem nachstellen.
00:08:45Es handelt sich um Cache Poisoning in React Server Components, Schweregrad 5,4 von 10.
00:08:49Dafür nutze ich eine Next.js-App und ein Fake-CDN, um eine echte Deployment-Umgebung zu simulieren.
00:08:53Wenn ich die Seite zum ersten Mal über die CDN-URL besuche und Produkte anklicke, ist es
00:08:57beim ersten Mal ein Cache-Miss und danach ein Hit. In den Logs sieht man das:
00:09:02Erst ein Miss für „/products“ mit Query-String, dann Hits. Als Nächstes habe ich den Cache geleert,
00:09:06um einen Ablauf zu simulieren, und sende nun diesen Curl-Request. Wenn ich jetzt in der App
00:09:10einen curl-Request an den Next.js-Server gesendet und gesagt: „Hey, kannst du in unserem Namen
00:09:15eine Anfrage an den internen Dienst senden?“ So haben wir diese Informationen erhalten und die Firewall umgangen,
00:09:19gibt die URL Server-Component-Daten statt HTML zurück. Next prüft dann beim Caching,
00:09:23um welche Art von Daten es sich handelt, und speichert sie entsprechend ab. Theoretisch sollte ein Nutzer,
00:09:28der die HTML-Version anfordert, niemals Server-Component-Daten erhalten. Das Problem:
00:09:32Durch unseren Query-String am Ende des Curl-Requests schlug die Prüfung fehl,
00:09:37da diese nur prüft, ob die URL auf „.rsc“ endet. Da unser Link auf den Query-String endet,
00:09:40hielt das System es für HTML und speicherte die Server-Component-Daten fälschlicherweise als HTML im Cache.
00:09:45Der nächste Nutzer, der die Seite aufrief, erhielt also die Rohdaten statt der Seite. Der Fix dafür
00:09:49war denkbar einfach: Bei der Prüfung auf die Endung „.rsc“ werden Query-Strings nun ignoriert.
00:09:55Kommen wir zur letzten Kategorie: Cross-Site Scripting (XSS). Hier habe ich eine Rekonstruktion
00:09:58mit einer Bewertung von 6,1 von 10. Es betrifft XSS in „beforeInteractive“-Skripten
00:10:02mit nicht vertrauenswürdigen Eingaben. Das heißt: Wenn ich in Next.js ein Skript-Tag
00:10:06mit der Strategie „beforeInteractive“ nutze und ein Attribut davon Daten aus einer unsicheren Quelle erhält –
00:10:11wie hier aus den Search-Params –, ist XSS möglich. Ich kann einen Nutzer dazu bringen,
00:10:15auf einen Link wie diesen zu klicken, in dem Schadcode im Search-Param eingebettet ist. Wer darauf klickt,
00:10:20sieht dann zum Beispiel das hier: Man denkt, man müsse sich neu einloggen, aber beim Klick auf „Sign In“
00:10:24sieht man, dass es ein Fake-Formular war, das über den Parameter eingeschleust wurde.
00:10:27Damit kann JavaScript auf dem Rechner des Opfers ausgeführt werden. Ein realistisches Beispiel wäre
00:10:32das Stehlen von Session-Cookies, um sich Zugang zu allen Konten zu verschaffen. Die Ursache
00:10:36Anfrage ist, also 200, 404 oder Ähnliches. Wenn also ein Statuscode vorhanden ist,
00:10:41zuerst das Skript-Tag und öffne dann ein neues mit meinem Code. Wenn ich Enter drücke,
00:10:45erscheint die Meldung „pwned“. Wie gesagt, man braucht ein Skript-Tag mit der Strategie
00:10:49„beforeInteractive“ und ein Attribut aus einer unsicheren Quelle wie den Query-Parametern. In Next.js
00:10:53wird dieses Tag in so etwas wie „dangerouslySetInnerHTML“ umgewandelt – der Name sagt schon alles.
00:10:58Dabei wird „JSON.stringify“ verwendet. Wichtig ist: „JSON.stringify“ maskiert keine
00:11:01HTML-Zeichen wie schließende Klammern. Das Skript sucht nach der Quelle und die restlichen Props
00:11:04enthalten die Tracking-ID sowie unseren manipulierten Wert aus den Query-Parametern.
00:11:09Das wird in den JSON-String gepackt und auf der Seite gerendert. In der finalen HTML-Struktur
00:11:14sieht es dann so aus: Wir haben das Skript-Tag mit der ID, aber dann folgt direkt
00:11:18ein schließendes Skript-Tag, das das ursprüngliche Tag beendet. Dahinter können wir jeden beliebigen
00:11:23Code ausführen. Der Rest am Ende sorgt dafür, dass keine Fehlermeldungen auf der Seite erscheinen,
00:11:27sodass keine offensichtlichen Anzeichen für den Angriff zu sehen sind. Das waren 13 CVEs
00:11:31für Next.js und React in dieser Woche. Ich weiß ehrlich gesagt nicht, was ich davon halten soll.
00:11:35Ich hasse das, und das sage ich als jemand, der vor zwei Jahren jedes Projekt mit Next.js umgesetzt hat
00:11:39und dachte, es sei die Zukunft. Aber es scheint eine Hürde nach der anderen zu geben.
00:11:44Es wirkt, als hätten sie Dinge überstürzt und müssten sie nun im Nachhinein flicken. Ich persönlich
00:11:47bin mittlerweile voll bei TanStack und auch bei Astro, wenn ich eine inhaltsbasierte Seite brauche.
00:11:52Die wirken auf mich viel simpler. Auch was Cloudflare in letzter Zeit macht, gefällt mir sehr,
00:11:58daher ziehe ich meine Projekte langsam dorthin um. Aber ich habe immer noch etwa 20 auf Vercel,
00:12:02die ich jetzt aktualisieren muss. Was denkt ihr? Werden Server Components jemals nützlich sein,
00:12:07oder sind wir damit gescheitert? Schreibt es mir in die Kommentare. Abonniert den Kanal
00:12:11und wir sehen uns wie immer im nächsten Video.
00:12:16---
00:12:20---
00:12:24---
00:12:29---
00:12:33---
00:12:37---
00:12:41---
00:12:46---
00:12:50---
00:12:55---
00:12:59---
00:13:03---
00:13:08---
00:13:12---
00:13:16---
00:13:19---
00:13:22---
00:13:26---
00:13:31---
00:13:34---
00:13:39---
00:13:43---
00:13:47---
00:13:51---
00:13:55---
00:13:59---
00:14:04---
00:14:08---
00:14:12---
00:14:17---
00:14:21---
00:14:24---
00:14:29---
00:14:33---
00:14:37---
00:14:41---
00:14:45---
00:14:49---
00:14:53---
00:14:58---
00:15:01---
00:15:05---
00:15:09---
00:15:14---
00:15:18---
00:15:22---
00:15:26---
00:15:31---
00:15:35---
00:15:39---
00:15:43---
00:15:48---
00:15:51---

Key Takeaway

Next.js weist 13 neue Sicherheitslücken auf, darunter kritische SSRF- und DoS-Schwachstellen im React-Flight-Protokoll, die eine sofortige Aktualisierung auf die neuesten Versionen zwingend erforderlich machen.

Highlights

  • Das neueste Sicherheits-Release von Next.js behebt insgesamt 13 Schwachstellen (CVEs), wovon 6 als hochriskant eingestuft sind.

  • Eine einfache Manipulation der URL-Struktur _next/data/[Build-ID]/[Seite].json ermöglicht das Umgehen von Middleware-Schutzmechanismen im Pages Router bei aktiver i18n-Konfiguration.

  • Durch das Senden von manipulierten Payloads mit 1000 Pointern und 200.000 Schlüsseln lassen sich 200 Millionen String-Vergleiche erzwingen, die den Server-Thread für mehrere Sekunden blockieren.

  • Eine Server-Side Request Forgery (SSRF) Lücke mit einem Schweregrad von 8,6 erlaubt es Angreifern, über den Next.js-Server Anfragen an interne Dienste hinter einer Firewall zu senden.

  • Die fehlerhafte Validierung der Dateiendung .rsc bei vorhandenen Query-Strings führt dazu, dass Server-Component-Rohdaten fälschlicherweise als HTML im CDN-Cache gespeichert werden.

  • In Skript-Tags mit der Strategie beforeInteractive maskiert JSON.stringify keine HTML-Zeichen, was das Einschleusen und Ausführen von Schadcode über URL-Parameter ermöglicht.

Timeline

Übersicht der 13 neuen Sicherheitslücken

  • Sechs der 13 identifizierten CVEs stellen ein hohes Risiko für Anwendungen dar.
  • Die Schwachstellen umfassen Denial-of-Service, Middleware-Bypasses, SSRF und Cross-Site Scripting.
  • Vercel empfiehlt allen Nutzern die sofortige Aktualisierung auf die gepatchten Next.js-Versionen.

Nach mehreren Vorfällen in diesem Jahr zeigt dieses Release die Instabilität von Server Components auf. Betroffen sind diverse Versionen des Frameworks, während alternative Lösungen wie TanStack konstruktionsbedingt nicht anfällig für diese spezifischen Lücken sind. Das offizielle Sicherheits-Release führt die Korrekturen als beiläufige Fehlerbehebungen auf.

Middleware- und Proxy-Bypass im Pages Router

  • Aktiviertes i18n im Pages Router schützt den Basispfad einer Route nicht vor direktem Datenzugriff.
  • Sensible Daten in Server-Side Props sind über die JSON-Datenpfade des Next.js-Builds ohne Authentifizierung abrufbar.
  • Der Fehler liegt in einem unvollständigen Matcher, der nur lokalisierte Varianten, aber nicht den Standardpfad erfasst.

Durch das Auslesen der Build-ID aus dem Quellcode lässt sich eine spezifische Daten-URL konstruieren, die die Middleware vollständig umgeht. Während Anfragen an lokalisierte Pfade wie /en/secret korrekt zum Login weiterleiten, liefert der direkte Aufruf der JSON-Datei unter /_next/data/ die geschützten Inhalte aus. Dieser Bypass erzielt einen Schweregrad von 7,5 von 10.

Denial-of-Service durch React-Flight-Protokoll

  • Die Deserialisierung von Server Actions weist eine quadratische Komplexität bei der Verarbeitung von Pointern auf.
  • Ein einzelner manipulierter Request erhöht die Antwortzeit von 0,02 Sekunden auf über sechs Sekunden.
  • Der Fix stellt das System auf eine cursorbasierte Verarbeitung um, was die Operationen massiv reduziert.

Das Problem entsteht, wenn das Protokoll nach spezifischen Pointern in einer langen Liste von Schlüsseln sucht. Ohne den Cursor-Fix musste der Server für jeden Pointer die gesamte Liste erneut durchlaufen, was bei großen Payloads zu 200 Millionen Vergleichen führte. Die neue Implementierung senkt diesen Aufwand von k * n auf n + k Operationen und verhindert so die Thread-Blockierung.

Kritische SSRF-Lücke und Cache Poisoning

  • Self-hosted Next.js-Instanzen sind anfällig für Server-Side Request Forgery mit einem Score von 8,6.
  • Angreifer können den Server als Proxy nutzen, um interne Netzwerke und Firewalls zu scannen.
  • Fehlerhafte Prüfungen auf die Dateiendung .rsc ermöglichen das Vergiften von CDN-Caches.

Die SSRF-Lücke betrifft primär Umgebungen außerhalb von Vercel und erlaubt einfache Anfragen an interne Dienste über den Next.js-Port. Parallel dazu führte ein Fehler bei der Handhabung von Query-Strings dazu, dass Server-Daten fälschlicherweise als HTML-Seiten gecacht wurden. Nutzer erhielten dadurch kryptische Rohdaten anstelle der gerenderten Webseite, weil das System Query-Parameter am Ende der URL nicht korrekt ignorierte.

Cross-Site Scripting in interaktiven Skripten

  • Die Strategie beforeInteractive in Kombination mit unsicheren Eingabequellen ermöglicht XSS-Angriffe.
  • JSON.stringify maskiert keine schließenden HTML-Tags, was den Abbruch des ursprünglichen Skript-Blocks erlaubt.
  • Angreifer können über manipulierte URL-Parameter Session-Cookies stehlen oder Fake-Formulare einblenden.

Wenn Daten aus Search-Params direkt in Skript-Attribute fließen, können Angreifer das Skript-Tag vorzeitig schließen und eigenen JavaScript-Code anhängen. Da Next.js diese Inhalte intern über Mechanismen ähnlich wie dangerouslySetInnerHTML verarbeitet, wird der Schadcode direkt im Browser des Opfers ausgeführt. Dies verdeutlicht die Gefahr bei der Verwendung von nicht vertrauenswürdigen Eingaben in Framework-spezifischen Skript-Komponenten.

Community Posts

View all posts