Im Mai 2025 wurde eine kritische Sicherheitslücke (CVE-2025-1974) mit der Bezeichnung "IngressNightmare" bekannt, die den in Cloud-Infrastrukturen weit verbreiteten Kubernetes-Ingress-Nginx-Controller betrifft. Diese Schwachstelle ermöglicht es nicht authentifizierten Angreifern, beliebige Konfigurationen in NGINX einzuschleusen, was zu unautorisierter RCE (Remote Code Execution) und einer vollständigen Kompromittierung des Clusters führen kann.
Im Rahmen des OPSWAT führten unsere Stipendiaten eine eingehende technische Analyse durch, um die Ursache, den Weg der Ausbeutung und die Strategien zur Eindämmung dieses hochgradig gefährlichen Problems besser zu verstehen.
Überblick über CVE-2025-1974
CVE-2025-1974 ist eine kritische Template-Injection-Schwachstelle, die in ingress-nginx-Versionen bis 1.11.4 und insbesondere 1.12.0 entdeckt wurde. Angreifer mit Zugriff auf Knotenebene eines Kubernetes-Clusters können diese Schwachstelle ausnutzen, um beliebigen Code mittels RCE über den ingress-nginx-Controller auszuführen, der standardmäßig über weitreichende Rechte verfügt, einschließlich des Zugriffs auf kritische Geheimnisse innerhalb des Clusters.
Das Kubernetes Security Response Committee hat diese Schwachstelle mit einem CVSS v3.1 Score von 9.8 (kritischer Schweregrad) bewertet:
Schlüsselkomponenten in dieser Analyse
Kubernetes Überblick
Kubernetes (K8s) ist eine Open-Source-Plattform zur Automatisierung der Bereitstellung, Skalierung und des Betriebsmanagements von containerisierten Anwendungen. Kubernetes-Cluster bestehen in der Regel aus mehreren Maschinen, die sowohl physische Hardware als auch virtuelle Maschinen umfassen können und gemeinsam hochverfügbare, skalierbare und verwaltbare Anwendungsumgebungen bereitstellen.
NGINX-Ingress-Controller
NGINX Ingress Controller (ingress-nginx) ist ein Open-Source-Ingress-Controller, der auf dem NGINX-Webserver aufbaut. Er arbeitet innerhalb eines Kubernetes-Clusters und fungiert in erster Linie als Reverse-Proxy und Load Balancer. Dieser Controller interpretiert die von Benutzern definierten Ingress-Ressourcen und übersetzt sie in umsetzbare NGINX-Konfigurationen, um den Datenverkehr in und innerhalb des Clusters zu leiten.
AdmissionReview und seine Rolle
Ingress-nginx integriert sich mit Kubernetes über einen Webhook-Dienst namens AdmissionReview. Dieser Dienst ist entscheidend für die Verarbeitung nativer Kubernetes-Ingress-Objekte und deren Übersetzung in validierte und syntaktisch korrekte NGINX-Konfigurationen. AdmissionReview gewährleistet zwar die Genauigkeit der Konfiguration, arbeitet aber unabhängig vom Ingress-NGINX-Controller und verfügt im Allgemeinen nicht über strenge Authentifizierungskontrollen. Dieser Mangel an strenger Authentifizierung ist ein Schlüsselfaktor, der zur Ausnutzbarkeit von CVE-2025-1974 beigetragen hat.
Ausnutzung von Schwachstellen und technische Analyse
Mechanismus der Ausbeutung
Im Kern beginnt die Ausnutzung von CVE-2025-1974 mit einer bösartigen Anfrage. Angreifer erstellen eine böswillige Anfrage an den AdmissionReview-Webhook und zwingen NGINX, eine gemeinsam genutzte Bibliothek zur Laufzeit dynamisch zu laden. Auf der Grundlage dieses Mechanismus analysierten unsere Mitarbeiter sowohl den AdmissionReview-Webhook als auch den NGINX-Workflow, um diesen Angriffsweg zu verstehen.
Schwachstelle bei der Injektion von Vorlagen
Beim AdmissionReview-Webhook wandelt die CheckIngress-Funktion bei der Verarbeitung eingehender Anfragen Kubernetes-Ingress-Objekte in gültige NGINX-Konfigurationsdateien um. Der Fluss läuft wie folgt ab:
- Jede Konfiguration wird geparst und an generateTemplate übergeben, damit sie gemäß den vordefinierten NGINX-Vorlagen formatiert werden kann.
- Anschließend validiert testTemplate die generierte Konfiguration anhand der zugrunde liegenden NGINX-Binärdatei.
Alle NGINX-Konfigurationen basieren auf vordefinierten Vorlagen, die in der Datei nginx.tmpl im Quellcode von ingress-nginx zu finden sind:
Innerhalb der generateTemplate-Funktion wird die Konfiguration wie im folgenden Code-Schnipsel dargestellt verarbeitet:
Die Validierung und Bereinigung der Eingaben ist jedoch unzureichend. Insbesondere wird das uid-Feld aus einem Ingress-Objekt direkt in die NGINX-Konfigurationsvorlage eingefügt, wodurch ein Injektionspunkt entsteht. Ein Angreifer kann dies ausnutzen, indem er eine manipulierte Eingabe wie uid="1234#;\n\n}\n}\n injection_value" eingibt.
Diese böswillige Eingabe ermöglicht die Injektion eines globalen Bereichs in das NGINX-Template, wodurch Angreifer beliebige NGINX-Direktiven auslösen und möglicherweise einen RCE ausführen können.
Von der Template Injection zur Remote Code Execution
Die Funktion testTemplate() wird erklärt
Nachdem die NGINX-Konfiguration mit der Funktion generateTemplate erzeugt wurde, erstellt die Funktion testTemplate eine temporäre Konfigurationsdatei und führt die NGINX-Bibliothek mit dem Befehl nginx -c {config_file} -t. Dadurch wird die NGINX-Binärdatei gezwungen, die Konfiguration zu analysieren und zu validieren.
Um die Schwachstelle auszunutzen, muss ein Angreifer eine Direktive identifizieren, mit der er bösartigen Code ausführen kann. Zunächst identifizierten unsere Kollegen die load_module-Direktive als potenziell nützlich, da diese Direktive es NGINX ermöglicht, externe Plugins zu laden. Allerdings ist diese Direktive nur in der frühen Phase des Konfigurationsparsings erlaubt, was nicht zu unserem Injektionspunkt passt.
Um diese Herausforderung zu lösen, setzten wir unsere Nachforschungen fort und stießen dabei auf die ssl_engine-Direktive, die wie folgt beschrieben wird: "Das Modul kann von OpenSSL während der Konfigurationsprüfung dynamisch geladen werden." Dies machte uns neugierig, denn die Fähigkeit, Module dynamisch zu laden, erforderte eine genauere Untersuchung.
Verstehen der ssl_engine-Richtlinie
Um zu verstehen, wie NGINX mit der ssl_engine-Direktive umgeht und unter welchen Bedingungen NGINX das dynamische Laden von zusätzlichen Modulen über diese Direktive erlaubt, haben wir uns den NGINX-Quellcode angesehen.
Beim Starten lädt NGINX seinen Anfangszustand und analysiert dann Zeile für Zeile die Konfigurationsdateien. Jede Direktive wird von der Struktur nginx_command_t behandelt, wobei die Direktive ssl_engine direkt die ngx_openssl_commands aufruft.
Bei der Analyse der Funktion ngx_openssl_commands entdeckten unsere Kollegen, dass sie auf OpenSSL-Unterstützung angewiesen ist, insbesondere auf die Funktion ENGINE_by_id, die für hardwarebeschleunigte SSL-Module verwendet wird.
Und bei der Analyse der Funktion ENGINE_by_id haben wir festgestellt, dass sie das dynamische Laden von gemeinsam genutzten Bibliotheken ermöglicht. Wenn die Bibliothek mit der Erweiterung __attribute__((constructor)) kompiliert wurde, kann die zugehörige Funktion sofort nach dem Laden ausgeführt werden. Dies deutet darauf hin, dass ein Angreifer durch Ausnutzung der ssl_engine-Direktive beliebige Shared Libraries auf den Host laden kann, was zu einem RCE führen könnte.
Gemeinsame Bibliotheken anvisieren und Angriffsstrategie
Um die Codeausführung zuverlässig zu erleichtern, muss im nächsten Schritt eine gemeinsam genutzte Bibliothek gefunden werden. Anstatt sich auf externe Bibliotheken zu verlassen, ergibt sich ein praktikablerer und kontrollierterer Ansatz aus dem Verhalten von NGINX selbst: der Client-Body-Buffer-Mechanismus. Diese Funktion ermöglicht es NGINX, große eingehende Anfragen in temporäre Dateien auszulagern, wodurch sich auf der Grundlage eines vorhersehbaren Dateiverhaltens Möglichkeiten zur Ausnutzung ergeben.
Wenn eine eingehende Anforderung mehr als 8 KB umfasst, schreibt NGINX den Anforderungsrumpf standardmäßig in eine temporäre Datei unter /tmp/nginx/client-body mit einem Dateinamen im Format cfg-{random_value}. Diese temporären Dateien werden bis zu 60 Sekunden lang zwischen erfolgreichen Abschnitten einer empfangenen Nachricht aufbewahrt.
Nachdem NGINX einen Teil der Anfrage in eine temporäre Datei geschrieben hat, wird die Löschung aufgeschoben, bis die gesamte Anfrage eingegangen ist. Wenn die Anfrage unvollständig bleibt und bis zu 60 Sekunden lang keine Daten empfangen werden, wird die Datei schließlich gelöscht. Durch das absichtliche Zurückhalten des letzten Datenpakets kann ein Angreifer die temporäre Datei jedoch in Gebrauch halten und sie so ausnutzen.
Obwohl der Inhalt der hochgeladenen Datei kontrolliert werden kann, ist das Auffinden der Datei im Dateisystem aufgrund des zufälligen Dateinamens schwierig. Der Speicherpfad kann mit client_body_temp_path konfiguriert werden, aber der Dateiname wird zur Laufzeit nach dem Zufallsprinzip generiert, so dass er nicht vorhersehbar ist. Diese Zufälligkeit erschwert den gezielten Zugriff selbst mit roher Gewalt erheblich. Um dies zu umgehen, nutzte das Team Verhaltensweisen, die dem Linux-Betriebssystem eigen sind. Betrachten Sie das folgende Beispiel:
This code opens a file and keeps it in an active state, closely mimicking the behavior of NGINX's client body buffer mechanism. Using /proc/{pid}/fd directory, attackers can find symbolic links created by the Linux kernel that map open file descriptors to their corresponding file paths. This route allows attackers to reduce the brute-force space to only two variables: the process ID (pid) and the file descriptor (fd).
Ausbeutung simulieren
Auf der Grundlage der obigen Analyse ist ein praktischer Ansatz für die Ausnutzung von RCE innerhalb des Ingress-NGINX-Pods:
- Hochladen einer bösartigen gemeinsam genutzten Bibliothek unter Verwendung des Client-Body-Puffer-Mechanismus von NGINX, um sie vorübergehend im Dateisystem zu speichern.
- Verwenden Sie Template-Injection, um einen Brute-Force-Versuch zu starten, der NGINX dazu zwingt, die zuvor hochgeladene Shared Library über anfällige Direktiven zu laden.
Erstellen der Nutzlast, die die gemeinsam genutzte Bibliothek enthält
Um sicherzustellen, dass der Code beim Laden ausgeführt wird, ist in der bösartigen Shared Library eine Einstiegsfunktion mit Konstruktorerweiterung definiert. Diese Funktion wird beim Laden durch NGINX ausgeführt und soll eine Reverse-Shell-Verbindung zu einem entfernten Host herstellen.
Nach der Kompilierung betrug die Größe der resultierenden gemeinsam genutzten Bibliothek bequem mehr als 8 KB, so dass sie von NGINX gepuffert werden konnte, ohne dass zusätzliches Padding erforderlich war.
Unsere Kollegen erstellten dann eine Anfrage mit einem überhöhten Content-Length-Wert (z. B. 1 MB), um eine Größenabweichung zu erzeugen. Dies veranlasste NGINX dazu, den gesamten Textkörper zu puffern, anstatt ihn sofort zu verarbeiten, um sicherzustellen, dass das freigegebene Objekt an einen vorhersehbaren Ort geschrieben wird.
Auslösen der Shared Library durch Injektion
Mit der gemeinsam genutzten Bibliothek haben wir als Nächstes eine bösartige Direktive in die NGINX-Konfiguration injiziert, die das verwundbare uid-Feld verwendet. Diese Direktive enthielt ssl_engine, das auf den gepufferten Dateipfad verweist:
Ein erfolgreicher RCE erfordert, dass die ssl_engine-Direktive auf den korrekten Pfad zur gepufferten Datei verweist. Dies kann durch ein automatisiertes Brute-Force-Skript erreicht werden, das systematisch mögliche Kombinationen von Prozess-IDs und Dateideskriptoren durchläuft, um den gültigen symbolischen Link zu identifizieren, der auf das gepufferte gemeinsame Objekt zeigt.
Nachfolgend finden Sie ein Beispiel für die generierte NGINX-Vorlage, die den Exploit ausgelöst hat.
Nach erfolgreicher Ausnutzung konnte der Angreifer Shell-Zugriff im Kontext des ingress-nginx-Pods erlangen, der standardmäßig Zugriff auf sensible Kubernetes-Cluster-Geheimnisse hatte.
Schadensbegrenzung und Abhilfe
Um die mit CVE-2025-1974 verbundenen Risiken wirksam zu mindern, benötigen Unternehmen eine Lösung, die Transparenz und Kontrolle über ihre Open-Source-Komponenten bietet.
OPSWAT SBOM, eine grundlegende Technologie innerhalb der MetaDefender®-Plattform, erfüllt diese Anforderung, indem sie ein Inventar aller verwendeten Softwarekomponenten, Bibliotheken, Docker-Container und Abhängigkeiten bereitstellt. Sie ermöglicht es Unternehmen, ihre Komponenten proaktiv zu verfolgen, zu sichern und zu aktualisieren.
Im obigen Beispiel scannte die SBOM-Technologie in MetaDefender Core™ das Paket nginx-ingress-controller, das die Sicherheitslücke CVE-2025-1974 enthielt. Das System stufte die Schwachstelle automatisch als kritisch ein und gab Hinweise auf verfügbare Korrekturversionen, sodass die Teams schnell Prioritäten setzen und die Schwachstelle patchen konnten, bevor sie ausgenutzt werden konnte.
OPSWAT SBOM ist in MetaDefender Core und MetaDefender Software Supply Chain™ verfügbar und ermöglicht es Sicherheitsteams, Schwachstellen schneller zu identifizieren und darauf zu reagieren. Mit OPSWAT SBOM können Sicherheitsteams:
- Schnelles Auffinden anfälliger Komponenten - Sofortige Identifizierung der von Deserialisierungsangriffen betroffenen Open-Source-Komponenten. So können Sie schnell handeln und die gefährdeten Bibliotheken entweder patchen oder ersetzen.
- Proaktives Patchen und Aktualisieren - Überwachen Sie Open-Source-Komponenten kontinuierlich mit OPSWAT SBOM, um vor Deserialisierungsschwachstellen geschützt zu sein. OPSWAT SBOM kann veraltete oder unsichere Komponenten erkennen und ermöglicht so rechtzeitige Updates und eine geringere Anfälligkeit für Angriffe.
- Einhaltung von Vorschriften und Berichterstattung - OPSWAT SBOM unterstützt Unternehmen bei der Einhaltung von Vorschriften, da die gesetzlichen Rahmenbedingungen zunehmend Transparenz in Software-Lieferketten fordern.